have you ever dreamed of becoming an in demand full stack engineer who can create stunning websites and impressive mobile apps well you're just one step away from making that a reality hi there and welcome to a new course where you'll build and deploy not one not two but three amazing applications these projects will level up your skills and turn you into an expert in both web and mobile app development and here's the cool part the skills you pick up from the first two apps are super transferable to mobile development your app will use the same react hooks components and even nextjs file based routing we'll start by building a fully functional online banking platform Horizon a platform that connects to multiple bank accounts displays transactions in real time and even allows you to transfer money to other platform users next you'll build care pulse a healthcare management system with the real-time SMS notifications to streamline the tedious checkup process after that you'll get an ultimate crash course on react native we'll start with the benefits of using react native why it has become such a popular choice for developing both IOS and Android applications and dive deep into Expo a framework recommended by react native to build mobile apps in 2024 and much more immediately after we'll put your skills to the test in the JavaScript Mastery Style by building and deploying a complete react native application called Aura a full stack platform form for sharing AI generated stock videos and are you worried that this might be too advanced don't be I'll walk you through everything from for management with react hook form and Zod to tailin CSS for styling all in a beginner friendly way by the end of this course you'll have a unique set of full stack developer skills and the confidence to build responsive web and mobile applications that truly stand out here are the projects you'll build the first project is a full-fledged banking platform called Horizon at the beginning you'll see a lengthy signup page since we're building a real world app not a fake one we need legit information no placeholders here once you sign up you must link your bank account this feature is powered by plate a stripe alternative used by a well-known Financial giant Robin Hood and many others test mode is free no credit card is required and you can use it anywhere in the world I'll use some test credentials provided by plate and we're in on this page you'll find all the details of your connected bank account account including the name balance and transaction list provided by plate on the right side there's a card and below that you'll see different spending categories on the next page you can view all your connected Banks balances and unique public IDs which you can easily share with others moving on we have the transaction history page with pation and filtering now let's transfer some funds once again there are many required Fields here just like in a real online bank we'll also need the recipient's bank ID so let me grab the bank ID from another account I've created there we have it just input the amount and the details and hit send back on the dashboard you'll notice a new transaction Row in the processing State like regular Banks it'll take some time to process the transaction it'll be added to the main bank account balance then you'll develop carep a healthcare management system that lets your users sign in using their phone numbers you can choose a country which automatically fills in its country code and then type the number and because this is my first time visiting this page I'll be redirected to the registration page where I'll need to register as a patient there is a ton of info to fill out including General details like name email phone number date of birth and more and your users also must provide medical information such as their primary care physician allergies current medications and all relevant medical history additionally they'll need to provide identification including the type and number of their ID along with a scanned copy of the document which you'll allow them to upload finally they review it and consent to the Privacy terms whoa that's a lot of info but you won't be cutting any Corners here this is a real Healthcare application after all once they've successfully registered they'll be redirected to the appointments page to schedule a new appointment here they can specif ify the doctor they want select the date and provide the reasons for the appointment along with any comments then a successful notification will appear leading us to the final confirmation page it shows that we've successfully requested an appointment to meet with a doctor and we'll receive a confirmation SMS from them soon we can also schedule a new appointment but let's put that to the side for now and explore the admin side of things back on the homepage you'll notice a small link on the bottom right clicking it will open up a modal where you must enter the pass key six wants in my case to access the admin page and there you have it we're redirected to the admin page where we find a wealth of health information including stat cards displaying the total number of scheduled pending and canceled appointments we also have a data table displaying the list of these appointments information about who request to them and two actions available for admins to take if everything checks out with a patient the admin can schedule or confirm the appointment with the designated doctor triggering a confirmation SMS to be sent to the patient let me schedule it and show you on my phone there it is a new SMS confirming that my appointment has been scheduled great I won't have to wait in line anymore the admin can also cancel the appointment but they must provide a valid reason the entire table includes proper pagination and it is fully responsive in fact in fact the entire application is designed to work seamlessly on all devices and finally you'll develop Aura a full Stack mobile app we'll cover the fundamentals of react native we'll discuss its different elements how it compares to react GS as well as NEX GS code structure file-based routing styling and much more by the end of this course you'll have a great understanding of react native and you'll be able to create your own apps using this powerful tool immediately after I'll put your skills to the test in the JavaScript Mastery Style by teaching you how to build and deploy a complete full stack react native application that's the only way to retain and expand on your knowledge with a visually appealing onboarding screen robust authentication system including both sign-in and signup screens Dynamic home screen showcasing the latest videos in an animated flat list with a comprehensive list of all videos with playback pull to refresh functionality full text search capability with a dedicated search screen tab navigation for seamless browsing a post creation screen where you'll learn how to upload videos and images and a profile screen offering detailed insights into your account all of this while learning nextjs with server and client side rendering group routes nested layouts server actions revalidation and more advanced and reusable form management with unique components like date picker Country phone input and OT verification using typescript react hook form and Zod played for payments and it'll work no matter where you are in the world charts shaten and Tailwind CSS for a modern completely mobile responsive UI react native elements like view touchable image flatlist scroll view safe area view text input status bar and more animations using animat table Expo file based nested routing and layouts Dynamic routing Tab and stack navigation context API and more backend using the latest open-source aight features including off databases file storage SMS notifications with twio and more all of that while making your code reusable and efficient and the best file and folder structure for organizing your code like a pro what about the prerequisites well all you need is a basic to medium understanding of react and nextjs if you're not there yet check out our nextjs crash course and come right back now with even better teaching methods where you'll get a completely open source codebase you can refer to if you get stuck free Custom figma Designs so you know exactly what you're building and even logical diagrams so you can visualize the application's high level architecture and a Discord server to get all your bugs resoled all those things are free so grab them from links below while I continue telling you more about the projects before we dive into the first project let's first create an account on aite we'll need it when building our apps in the description down below you can find a special link that allows you to follow along and see exact ex actly what I'm seeing in the video and you also get some additional credits click get started sign in with GitHub and that's it you're about to take a deep dive into the transition from react to nextjs to react native and learn how to connect all those dots to become an ultimate full stack developer someone who can do way more than just build websites and apps you might have seen plenty of videos on these topics maybe even on my channel but this one is special it's your allinone guide to understanding the differences and connect C between these different Technologies I think you're ready to get started so grab your coffee and let's dive into building out our very first project are you bored of those financial trackers that are basically just to-do apps where you add income deduct expenses do some math and then show it on a chart it's time for a change I hope you're excited as I am not many developers can say they can build a banking system but you'll be one of those who can so let's dive right into the code to get started building our one of a kind banking application will start from bare Beginnings by creating a new empty folder on our desktop let's call it JSM Banking and you can drag and drop that empty folder into an empty Visual Studio code window once you're there you can open up the terminal and we are ready to get started in this course to build this online bank we'll of course use react which is the best component library for the web web of course we won't use react alone we'll use nextjs on top of it the best react framework for the web used by the world's largest companies enabling you to create highquality web applications with the power off react components and when it comes to the banking functionality we'll be using pled one of the world's leading banking apis today allowing us to turn this app into a real banking application and not not just a budget tracker which you can see on many other YouTube videos we'll use ples sandbox mode allowing you to follow along with this video and learn how to implement all of the functionalities in this video no matter where in the world are you you'll be able to follow along using the free sandbo account and when it comes to merging those transactions to our real database will use aite it will allow you to build your entire backend within minutes and scale effortlessly using the completely free open- source platform so everything we're doing is completely open source from authentication to databases functions storage and more aite is becoming one of the go-to open source tools for backend development so to follow along with this video and see exactly what I'm seeing while developing it click the special app right link down in the description click get started and sign in with GitHub this will bring you to the dashboard allowing us to get started using the app and what would the banking app be without proper charts so we'll be using the best chart library in the market called chartjs which allows you to create any kind of chart you can imagine so you learn how to work with it too to style our application we'll of course be using Tailwind CSS which is a utility first CSS framework allowing us to have completely custom Styles and have them quickly without having SE SE CSS files we'll power up our Tailwind CSS using shat CN which is a component Library built on top of it allowing you to have any kind of component you might need in your app such as simple buttons alerts alert dialogues and more it is my go-to UI kit nowadays and of course our banking app has to be secure so we're going to go a step further and teach you how to implement Enterprise level application monitoring software with within your application specifically we'll Implement session replay allowing you to get to the root cause of an issue by watching replace of real user sessions within Sentry and that works even for banking application because Sentry automatically hides all sensitive data so as you can imagine we'll cover a lot of ground so grab yourself a cup of coffee or T and let's get started to initialize our app we can actually use shatzi and starter so let's go to get started and installation choose next GS and then let's copy the initial command I'm going to paste it but instead of my app right here I will say slash and you can say the same that will make sure to create it in the current repository so press enter and press Y in this case we have to answer a couple of questions we don't need a source directory we will use the app router no need to customize the default and that's it next GS is getting initialized as you can see react and react Dom nextjs on top of it and then we have additional dependencies such as typescript so yes we will be using typescript with this project if you haven't used it before don't worry I'm going to teach you how to do it it will simply allow us some additional type safety and make our application that much more more secure we'll also be using tailin CSS for styling and even es lint to make sure that our code base is clean so overall this is a big project a lot of things to cover but don't worry I'm going to take you there step by step and on the topic of reaching Mastery I just couldn't not mention the nextjs course that we created not that long ago it has become the best nextjs course on the internet and a lot of companies are using nextjs as I told you at the start and it's all about understanding how to use next in a way that it should be used not just like good old react and at the start I was using it like good old react too but then I noticed that that results in a performance that looks like this rather you want to get to something that looks like this and within the course we dive deep into complete understanding of how nextjs works then build build and deploy a complex app same as you'll do in this video and then we even have active lessons to test yourself because sometimes it's easy to just see me do it but in the course I'll actually challenge you with the task example resources and even hints so you actually write some additional code I just wanted to let you know that if at any point in this video you feel like it's too hard then it might be a good idea to pause it and postpone it until you complete the ultimate nextjs course but nonetheless I'll do my best to explain as much as possible in this course too so with that in mind we have created a JSM banking folder which means that we can follow the second step right here which is installing shat CN so let's simply paste this command and just press enter for all of these and it will soon enough get initialized we also need to set up the fonts which will do soon enough and we also need to set up the tail config which I'll show you how we can do very soon other than that the way that Chad scen works if you haven't used it before is it creates a new folder and adds the code only for the components you actually want to use within your application which is not the case for many other UI kits for example material UI or bootstrap there you install the whole library and you might not even need it so let's see how does it work for a single component we can first copy the installation for the button and then paste it in our terminal MPX chatsi and UI latest ad button it will install the button and if you go right here in our file explorer go to components and then UI you'll notice there's an additional folder here there's a button component within it and it does seem like a lot of code for a button but don't worry you never have to dive into these files yourself you can simply use that button later on within your code and then modify only if you need to with that in mind before we run our application I want to make sure that you have access to the complete figma file for this entire project and the link to access it will be down in the description it is as simple as going there clicking download and putting your name and email as soon as you do that you'll get access to this figma file with a complete design we're going to do everything starting from the authentication to a detailed dashboard with connected cards bank accounts and transactions and yep you'll be able to connect multiple bank accounts and you'll be able to see a complete transaction history for each one of the accounts but it doesn't stop there will also implement the functionality to transfer money from one horizon account to another and by the way that's the name of our bank Horizon so you'll be able to send money between real bank accounts right within our application just like you can do in a real banking application making apps like this needs a lot of careful planning and figuring out exactly how everything should fit together so even before you start building you've got to know exactly how it all works and flows step by step so to help you learn better I've put together a complete flow chart going through absolutely everything you need to know about how this app works how the flow works how the money gets transferred all of it is laid out neatly in a mind map and I'll go through it in detail in the video but if you prefer to study it on your own time you cck the link in the description and get it for free now hiden Within These figma Pages there's going to be a lot of these little icons or images or Styles which we need for development and for that reason I went ahead and prepared some assets for you to make our development and Learning Journey easier and for that reason I prepared some simple assets to make our development Journey smoother so first things first we can delete the favicon and the global CSS from the app and we can delete the lib folder as we'll create a new one from scratch and same thing goes for the public as well as the staling config great with that in mind in the description down below you can find complete assets which is going to be a zipped folder so download it from Google Drive and don't worry if it says that it might have viruses Google doesn't know what they're talking about trust me there's no viruses there download it unzip it and then simply paste it into the root of your directory within the assets you'll see that we have the app so from the app pull the globals into our original app and you can then delete it if it's easier for you pull the constants outside lib public types and Tailwind config put all of that into the root of your directory and you can then delete the assets so let's see what we brought in starting from the bottom we have the taal wi config this file has already been there before but in this case I have simply added some of the colors which I picked from the figma design so you can see the back gradient Indigo success colors and so on on so the next time you want to use this uh green color like this one here you don't have to say something like text Dash and then use this very specific 054 F31 rather you can just say something like text- success 900 that is the idea of doing this and if you're wondering how I pull these values from figma well let me show you back into figma file I think this is that success color you can click on a specific component and then on the right side you can see the corresponding Styles specifically if you go on their properties so let's try that one more time let's say that I wanted to get to this green background color right here I would just click multiple times to get to that level and you can see this background color right here and then you can just put it here in a way that makes sense for you on top of that we also have the types which will include some of the typescript types we'll use throughout this video for example the parameters for all of the fields within our o form then we have the public with all of the icons we're going to use the lip folder with utils where to be completely honest I mostly use some chat GPT to generate these for me so for example we're talking about formatting the date formatting the amount parsing the string or or removing special characters these are mostly functions that we can generate together using chat GPT later on on top of that there are some constants such as sidebar links like in the sidebar we'll have five different routes and each route has a route as you can see here but we also have to add the image and the label to it so it looks good so I just took some time to create this array for you as well as some mock data and finally there's the global. Cs s s inside of which we import tailwind and make some modifications to our base Styles such as hiding the scroll bar changing the color and implementing some additional specialized Styles which we cannot easily do with Tailwind so rather I just manually Target some properties and apply them here as well as create some special Tailwind Styles so for example we're going to have many inputs in our application and I can even show you that if we go to our transfer form you see how many inputs we have here it's a lot and they all have similar Styles so instead of every time saying Tex 16 placeholder rounded border and so on we can just create a utility class called input class and then by using it it will apply all of the other class names I'll teach you how to create some utility classes as soon as we use our first one and that's it we are just warming up you will do everything else that will come with this project and it won't be easy at times it will be very hard but you and I will go through it together so before we even run our app let's go to the app and then layout we want to fix this metadata and import a different font alongside enter we'll also be using I am ibmor plexor serif coming from next font Google to this enter next to subsets we want to give it a variable equal to-- font denter and right below we want to create a second font con IBM Plex serif is equal to we call this IBM Plex serif Constructor and we pass an object with options with subsets of an array of Lain we also want to do a weight of an array of 400 and 700 as strings and want to pass a variable for that font which is going to be D- font D IBM DPX Das serif great we can now change the metadata by giving our app a title which will be horizon or Horizon Bank we can also give it a description which will will be something like Horizon is a modern banking platform for everyone and we can also give it icons with one icon of forward slash ions for/ logo.svg this is now coming from our assets next we have this root layout which was created for us by nextjs and we have a body where we're using this inter but we want to style it in a way that it's going to be a template string where we use the enter. variable and the second one will be IBM Plex serif Dov variable this basically allows us to use those fonts across our entire application now let's create our homepage and you could create it like this where we have a simple page. DSX but that way we can only have one single layout and what is a layout well a layout is specific UI that you can see across multiple Pages for example notice this sidebar right here and notice it here it is shared across pages and do the off Pages have it they don't which means that all of the homepages or root pages will need to have one layout and the off Pages such as login and sign up we'll use a different layout to implement that we'll use a special nextjs functionality called route groups typically nested folders are mapped to URL paths you know that file-based routing right but you can Mark a folder as a route group to prevent the folder from being included in the URL path and this is used for two reasons organizing routes into groups or enabling nested layouts which is exactly what we want to do and the only thing you have to do to implement nested layouts is wrap the folder name within parenthesis such as this so let's remove this page and let's create a new folder called root like this and within it we can create a new page. TSX and a layout that will only be used for this route group Group which of course will have that sidebar in the page right now we can run rafc which will create a simple react Arrow function with an export and we can call it home we can also say home right here or you can even call it a dashboard for the root layout we can copy what we have in the original app layout and paste it there but it will be much simpler we don't need to import the metadata nor the fonts nor the the global CSS we only have to export a single layout remove all of the class names from the body we don't need the body at all nor the HTML rather we'll return a semantic main tag as this will be our main part of the content inside of which we're going to show a sidebar so let's write sidebar here and right below the sidebar will render the children does this make sense so we have this primary layout which is mostly used to just wrap it with different fonts Styles or metadata and then we have a special layout which will be used for all of the main components such as the home dashboard transactions all components that use a sidebar and then we're going to have a separate route group right here called oth which will have its own layout. TSX which we can copy right now from the root layout paste it here but this one won't have the sidebar and it will be a bit different okay that's the idea and while we're creating the file and folder structure within our o we're going to have two new pages or folders for now sign in which will have its own page. TSX where we can run rafc and call it sign in and we're going to have another folder called sign- up inside of of which we'll have a page. TSX and there we can run rce and it's going to be called sign up if this rafc isn't working for you it's basically just a shortcut to generate this snippet of code and it's coming from an extension es7 Plus react Redux react native Snippets so you can simply install it reload your Visual Studio code and it should work but with that in mind I hope that you now understand how these route groups work if it's still a bit unclear you can browse the docs or check out the ultimate nextjs course where we have a dedicated section just on routing as you can see we start with routing the core architecture of nextjs and then immediately go over the multiple layouts and group the routes but for now we might as well run our application and explore it in action so let's run mpm randev to run our application for the first time and let's open it up on Local Host 3000 there we go it's running and I want to give you a white screen flash warning if you're in a dark room on a dark monitor the whole screen will now turn white 3 two 1 and there we go we are on our homepage so you can see here that we're on Local Host 3000 and we have a sidebar and then the homepage right that's the idea and if we now go to for/ sign- in you'll see that it's just sign in without the sidebar that's the idea and you might be wondering why am I not going to root and then forward slash or why am I not going to O and then sign in this is a 404 why is that the case why is it just sign in without o well when you create route groups they're not added to the file based routing they're just used for you to create a layout and create meaningful grouping then only the folders within it that don't have the parentheses within them count as additional routes cool so now we have our layout we also have our homepage on Local Host 3000 and that means that we are ready to start creating the layout great job on coming this far and I have to be honest this was the most boring part of the video but now we dive into the exciting stuff creating the layout out with a nice sidebar modern UI and immediately showing this welcome message which you need in every application and you'll see it much more often nowadays as the goal of modern web applications is personalization even on JS mastery. proo we have recently added it here it just makes the experience that much better next we'll immediately learn how to use chartjs to create this simple chart and add the total current balance so with that in mind we can soon start with the homepage but I also want to do something special for this course to improve your learning experience and that is push the current code to GitHub and continue adding new commits consistently as we go feature by feature so that way if you get stack up to this point you'll be able to check the code base at a specific point in time and that way it'll be easier for you to debug and if you want to you can also commit your code whenever I push that way you'll get into the good habit of committing consistently so let's go to GitHub and go to this plus button and click new repository I'm going to call it Banking and I will make it public I want to make sure that all of the projects that I ever post are completely free and open source that way you can learn from them you can take the code and do whatever you want with them even for paid courses yep you heard that right in the ultimate nextjs course you will build and develop Dev overflow which is a modern stack Overflow clone applications packed with features it has AI built in a complete recommendation System complete Global search code blocks what you see is what you get editor and more and we build all of this within the course and if you go to my GitHub profile and search for overflow you can immediately see a stack Overflow next gs14 course and the complete code for this entire project is available for free on GitHub feel free to check it out and give it a star and if you like what you're seeing you might want to follow along and have me teach you how to do it with that in mind I will create a new repository and we can use the help here to push our existing code to it so going back to application we have now done a lot of work our entire initial file and folder structure has been done so let's open up the terminal let's actually split it so we have more space to work here and I'm going to say get init to initialize our repo then we can do get add dot to add all of the current files to it and then say something like get commit dasm and then we can add our commit message and say something like Implement initial file and folder structure another Pro tip whenever you're writing these commit messages always write it in imperative form which means you have to say Implement not implementing or implemented that's because you should be asking yourself the question what will this commit do when merged to main this commit will Implement initial file and folder structure it's just the most common practice that is used across development companies of all sizes around the world so now you know how to do it let's press enter then we need to Branch over to the main we only have to do this at the start get Branch dasm Main and get remote add origin and get push U origin main we only have to do these at the start with that we can now close this terminal you can see no more files are being tracked by our source control and if we reload our page you can see all of the existing files are here what I also like to do is immediately add some kind of a description we can copy the one from our primary layout which we have here Horizon is a modern banking platform for everyone for now we can leave the website empty you can add some of the topics X gs14 and remove all of these here that's going to make it a bit cleaner and now for every other commit let me show you how you'll be able to get access to the code up to that specific point of building this application you go to commits right here you click on a specific commit you can see this is the initial one and then this is the one that we have added right now you can see all the changes and this might be enough for you but if you want to get a snapshot of the entire codebase at the time when this commit was added you just click browse files right here at the top and then you have the complete file and folders structure up to that point of building the application so whenever we Implement some of the feature we'll try to remember to do a quick push great now let's focus on the home dashboard first I'll split my browser and visual studio code view so you can see everything at the same time and we can start by turning this div into its own section we'll also give it a class name of home this is one of those situations where home is not a native Tailwind CSS class name but if you go to search and search for home you should be able to see it right here where we apply some of the classes so this will remove the scroll bar and make it a flex with a full width Flex row and apply some of the responsiveness properties now right within this section we can also create another div and this div will be a wrapper with a class name equal to home- content so this will be the primary part of our homepage and within it we can create a header component with a class name equal to home Dash header right within that header we can write something like welcome Adrian and here you can put your name and as you can see it has a bit of a padding and margin and it's nicely rendered right here in the center now this welcome Adrian will be a new component as as we want to reuse it multiple times and we can easily tell that now because we have a complete design so you see this welcome Adrian alongside the subtitle we have another one right here and we have one here as well it's basically a header on every single page so with that in mind let's extract it into its own component by going to components and creating a new component called header box. TSS X and we can run our afce and we can immediately just call it right here header box coming from components header box and you can immediately import it and call it as a self-closing component that's going to look something like this now to it we'll have to pass a couple of props and what kind of props do we need to add well first of all the type of this specific header box sometimes it will be greeting such as in this case where it's going to say something like welcome and then the username and other times it will be just a regular header to indicate which page we're on we can also provide a title which in this case will be welcome and we can provide the username that will be equal to the first name of a user or just a guest so for now since we don't have the user implemented maybe we can just say guest or or let's immediately do it properly by creating a new variable at the top called const loged in which will be equal to an object with a first name and here you can put your own first name I'm going to do Adrian and now as we pass the user we can make that equal to logged in question mark. firstname or guest in case we don't have a username and finally we can pass a subtext that subtext will be let's see something like access and manage your account and transactions efficiently there we go and now we can go into the header Box by holding the alt or command key and clicking on it and we can accept all of these props at the top such as type which by default will be equal to title if we don't pass anything else title subtext and the user and since we're using typescript we can Define these types as header box props and you can see that we didn't have to import that from anywhere those header box props but it immediately knows what they are it's a typescript interface and we can again command click to go into it it's going to lead us into to our special types index. D.S file that contains all of our interfaces and it knows exactly what this component needs it wants a type which is optional of a type title or greeting it has a title subtext and a user property which is optional as well so now for example if we go back and if we remove the title from here you can see that it's complaining saying that the title is declared that's why you use typescript great now let's implement this header Box by returning a div with a class name equal to header dashbox and we're going to give it an H1 right within it and that H1 will render the title let's style it a bit by giving it a class name equal to header dashbox Das tile that's going to make it bolded and let's put it into multiple lines and below the title we can check if the type is triple equal to greeting and if it is only then we can render an additional span element that will render the user so welcome Adrien we can also give it a class name equal to text- bank gradient there we go and let's put this user in a new line and let's give it an empty space character by saying add mbsp and semicolon and that's going to give it that space right below this H1 we can render a P tag that will render the subtext and we can also give it a class name equal to header dashbox Das subtext there we go now we can also zoom out so you can see how it should look like there we go and that was it for our header box now going back we can go below that header box and we can render another custom component it'll be a balance box letting us know the amount of money we have in our account so let's create a new component and let's call it total balance box. TSX run RFC and use it right here total balance box there we go to it we'll also have to pass some props such as the accounts which will be all of our accounts that we have and for now we can make that just an empty array we'll also pass total Banks which is the number of banks that we have for now I'm going to say something like one and finally we need to pass a total current balance which will be the amount of money we have right now also a number and I will make that something like 1,000 250 let's also add some sense like 35 now we can go into that box and start implementing it we of course need to accept those props by saying accounts and if we don't pass anything it can default to an empty array we need the total Banks as well as the total current balance and that'll be of an interface total balance box props next we can turn it into a section and we can give it a class name equal to total balance now it looks like a card immediately within we can create a div which will act as a wrapper for our chart so let's say class name total balance chart and there very first we'll render our first donut chart that's going to look something like this but for now let's go below this div and let's create another div this one will have a class name equal to flex flex-all and a gap of six within which we'll have a new H2 that will have a class name equal to header das2 and it will render the total Banks and then bank accounts so we know what it's referring to so it says One bank accounts in this case we have that extra S at the end even though it's one so we can basically put this first and then say bank accounts and then column this way even though it's one it's going to look good so bank accounts one later on it's going to be 2 three four and so on then right below that H2 we can render a div and that div will have a class name equal to flex flex-all and a gap of two and right within it we can have a P tag that's will say total current balance we can also style it a bit by giving it a class name equal to total balance label and right below it we can have one final P tag that will have a class name equal to total balance amount FL X Center and a gap of two now sure what we could do here is first of all just render the total current balance that's one way to do it but this doesn't seem like a dollar amount or any other currency for that matter so first let's properly format it what we can do is we can call the format amount utility function and then pass this as the first parameter as soon as we do that you'll notice that it will try to use this format amount which will actually format it as an American dollar and you can use any currency of choice you'll just have to figure out how to modify this international number format to something else it should be pretty simple but the reason why we get an error right now is because this utos file uses a package called query string for another one of our utility functions so we need to install it so let's split our terminal and run mpm install query Das string we'll use this to modify our query parameters later on and as soon as we have done this you can see that now this looks like an actual number with dollars with a comma right here and then the sense but we're going to take it a step further we'll use a special count up package that will allow us to count up to the number that we have which is going to give this very nice effect of slowly counting up to the total amount for that we'll use the react count up package so let's simply install it by saying mpm install react dount up and press enter and then we can head over to usage and you can see how we can use that package the simple example is to just call it like this count up so let's do just that if I go right here and render the count up component we can import it right at the top by saying import count up from react countup and let's see how does it look like with end of 100 and now we get a very interesting error saying error use ref only works in client components add the use client directive at the top to use it but wait even if you knew that we cannot use hooks in server components which by default every component is a server component unless you say otherwise you might say but where are we using the US ref I don't understand why is it blaming me for something I didn't do well this is a great lesson sometimes external packages will use some client side functionalities within themselves even though you cannot see it it's there and it is using the used ref so we would have to either turn this entire component client side or a proper solution here would be to create a new component inside of which we can use countup so let's do just that let's call it animated counter and we can create it as a new component right here animated counter. TSX run RFC and now we can properly import it to it we can pass just the total current balance as the amount is equal to Total current balance we don't even have to format it as this animated counter will do that automatically for us so it's even simpler now we can go into the animated counter we can accept the amount which is of a type amount is number and we can just pass the amount and see how it quickly counts up to 1,250 we can also add the dollar sign up front to make it look better and over here we can see which props might be interesting to pass so we have the start the end the duration so sure we could maybe add maybe a decimal there we go this is very good and the prefix this will allow us to choose the currency and I think that's more or less it that we need we can also modify the duration so so going back let's give it some more properties such as a decimal and a prefix of dollar sign now I can remove this one here indent it properly and check this out that's great we can also add the duration and the number of decimals so let's copy the duration make it [Music] 2.75 and let's add not four decimals currency typically only have two decimals and check this out looks even better we can maybe even increase the duration into something like 4 seconds no that's way too much it makes it seem like we have more money than we actually do so let's just leave the default amount I think that will be okay there we go wonderful looks great feels great let's also give this div a class name equal to w-o and now let's go back and let's finalize this View by finally doing our donut chart the first chart of many for that we'll be using chart.js so let's go get started and let's navigate to the installation there we go it is just mpm install chart.js great and then how do we use it within react well let's search for react right here react charge maybe here stepbystep guide react there we go framework Integrations is what we want and we're looking for react chars 2 great it even has its own mpm page and we need to install another package by running mpm install react-js 2 and here is how you can import different components so let's give it a shot let's create a new component for this chart called donut chart right here TSX run RFC and let's copy everything we have here and paste it at the top the Donut of course needs to be used within this div and this donut of course will be the only thing that this donut chart will return and the reason that we had to use it within a new component is because it is a client side component so we have to give a use client directive on the top now if we go back we're going to get one error that's fine we're going to fix it soon we have to modify the data we're passing to it and you notice that while going through this course I refer to a lot of different documentation Pages quick start for chars for that countup Library even for react chars too you always need to refer to documentation and that's something that I want to teach you in every single JSM course as sure I can just show you how to do it but if I teach you how to do it the next time you'll be able to do it the next time the next time and the time after that and that's when you truly become a great and independent developer so with that in mind we have to figure out what data this is so we can check the charj dynamic data set okay that's a good one and we can maybe take a random data set for now let's see if we have some data that we can extract yeah this is a good example it has data sets and it has labels so instead of copying it let's refer to this and let's create our own data set we can do that by first accepting the accounts that we want to pass accounts is equal to accounts of a type donut chart props and now we can pass the accounts right here to this donut chart that we're going to call by saying accounts is equal to accounts coming from props and of course we have to import the chart at the top now going back to it we can start forming this data by saying cons data is equal to an object and now we have to form it in a way that charj will accept it so as you can see on the right side it needs to have a data sets array so we can say data sets will be equal to an array with an object with a label of Banks and then we can pass the data which will be some kind of an array of different balances that we have in that bank account for example let's do 1,250 2,500 and maybe let's do 3750 just as an example you can also pass different background colors so we can say background color will be something like Let's do an array of hash 0747 B6 let's do a second one of hash 2265 d8 and let's do hash 2f 91f and you might wondering why are we typing this if we have added them to Tailwind config before well we're not directly adding the Styles or class names here this is within JavaScript and this belongs to the chartjs so we cannot simply say something like text- blue right here if we go back now it will break as it's trying to map over our data here but we're not yet done forming the data alongside data sets we also need to pass labels and this will be an array of different strings for example we can name different banks like test one or let's do Bank One let's also do Bank two and let's do Bank three and now we can use this data and pass it as data to our donut there we go take a look at this even though it's small our chart is here but let's first resolve this error the error says hydration error p and then animated counter I think I know what that is animated counter already is a P tag so we cannot put a p within a p we have to put it within a div so if we do this and properly close it the error is gone the money is counting up and we can see our great looking chart showing us how much money we have in different bank accounts we can also apply some additional options to it by expanding it and right here we can say options is equal to an object where cutout is 60 % so you can see you can modify how big or how wide these circles around will be so going from a bit wider to maybe smaller with 60% we can also modify the plugins specifically the legend which we will make a display of false as we don't want to see the legend we just want to see this big thing and see how much money we have in our bank accounts that is phenomenal great now I can exit this we're also done with the total balance box and if I expand it would you look at that it looks great and if I expand it you can see how the chart also slowly opens up the money starts counting up and looks great of course it looks a bit empty right now as we don't have the left sidebar nor the right sidebar but we'll do that very soon for now it's important that we know how we can count our money up and how we can show it within our first chart ever using using chartjs with that in mind I don't want to dive into transactions just yet as for that we would need to have some real data I would rather want to see this look good once we implement the left sidebar and the right sidebar therefore completing our full layout so let's start with the left sidebar first I think that's going to make our app look completely different so going back to our homepage we want to move from here and we want to go into the root layout and here we can start implementing the sidebar so let's give this main a class name equal to flex h- screen for full height W full for full width and font Das enter that'll make it look like this as it will position the sidebar on the left side of the content now we can turn this sidebar into an actual component by creating a new component called sidebar TSX where we can run our afce and we can now import it right here sidebar coming from here importing it from components sidebar within that sidebar we'll have to have some knowledge about our currently logged in user so for now let's mock it by saying con logged in is equal to just an array with a first name of Adrien and let's also do last name of JSM later on we can fill in additional information here but it won't even be necessary as we'll automatically be fetching this data from a real user and now we can pass this logged in as the user right here let's dive into the sidebar let's accept that user right here and it will be of a type sidebar props so if you want to see what the user will have you can see that we have a custom model or type right here for the user it has to have an ID email user ID and more we'll add things as we go but for now it's good that we have the user here let's turn this div into a section and let's give it a class name equal to sidebar as you can see it automatically got hidden on mobile devices so we need to go a bit wider here if we want to continue working on it I think around here we can start seeing some white space here on the sidebar so let me collapse the visual studio code as well and let's continue working on it within this section we're going to have a nav as we want to navigate within the sidebar with a class name equal to flex flex-all and a gap of four within it we want to have our first link so this will be a link component which which will come from next link every link has to have an href this one will point to the forward slash meaning the homepage and it will have a class name equal to margin bottom of 12 to create some spacing it'll also have a cursor Dash pointer to make it clickable items Das Center and a gap of two and within it will render a self-closing image property image of course being the nextjs image we can import from next image we can give it a source equal to SL ions for/ logo.svg and as it's an xgs image it also has to have a width property of 34 and the height property of 34 as well and now we can see the logo appear on top we can also give it an Out Tag of horizon logo and we can give it a class name equal to side is Dash 24 pixels inside of square brackets and on Max Excel devices size of 14 there we go that's a bit bigger right below it we can render an H1 and this H1 will say Horizon and we can also give it a class name equal to sidebar Das logo we cannot see it right now but on larger screens it is there now let's go below this link and let's create links pointing to all of the other Pages within our application we can do that by mapping over sidebar links which is coming from constants so one more time to repeat I have created an array of five different objects that have label route and the image URL that way it's easy to just say map and get each one of these items and for each item open up a new function block where we can return a new link that will have an href equal to item. Route it will have a key equal to item. label and within it it can render item. label as well and here it was supposed to be route instead of router if we do this you'll notice that we have four or five links here but they're white so we need to add some additional styling let's do that by styling our link first by giving it a class name and here for the first time in this course we want to make a specific class either active or not active if we're in the homepage we want to make sure that that home link has a different class name you can see exactly what I mean on our design so to do that we'll have to use a special package package called CN that stands for class names and it's coming from lib utils you basically call it as a function and as the first parameter you pass it any class you typically would like a sidebar link right here but then as the second parameter you give it classes which will trigger depending on specific events such as we can figure out if our link should be active and it should be active if that's the path that we're currently on so let's first get access to the path Name by saying const path name is equal to use path name coming from next navigation and now that we have it we want to check out whether the path name is triple equal to item. route or if path name do starts with a template string off item. Route and then we add forward slash outside of it and here again it's a route now as the second parameter here we can add an object where we can say apply a BG Bank gradient class only if is active is true that's how it works and now we have to turn this sidebar into a client side component because we have used a hook so at the top I'm going to do just that use client and now it's working again but it doesn't seem to be applying it so let me just expand it a bit to see what's happening we have a BG yeah I misspelled the class name it's gradient and now if I go back right here there we go now it says home and if you want to learn more about server and client components in nextjs their documentation is a phenomenal place to start only if you need to use some browser functionality like hooks or routing or stuff like that you can turn it into client side component and there's this great documentation page on nextjs saying server and client composition patterns where it basically tells you when each component needs to be either server side or client side basically if you want to fetch data access the backend keep sensed information or reduce client side JavaScript you would use server but in any other situation if you need to add interactivity or event listeners like onclick on change use any kind of hooks or browser apis or custom hooks even you need to turn it into a client component or another rule of thumb is keep working on server side unless you get an error if the error says to switch it then you can switch it to the US client easily of course that's way oversimplified we go into way much more depth about serers side rendering server actions and different types of data fetching within the course but even this table should be fine for now so now let's complete the rest of the styles by going down right here and instead of simply returning the item label let's return a div that will have a class name of relative and a size of six within it we can render an image and that image will have a source equal to item. IMG URL an Al tag of item. label it will have property of fill and let's save it you can see that now we have these different icons appear here but the first one is a bit too dark for this gradient that we have so how do we fix that you might think that we need two different versions of icons one that we show when it's not clicked and the other that we show when it is clicked but we can use the same image and then fix it with CSS let me show you how we can create a new class name where we're going to use this Dynamic CN property and modify the brightness dash3 and invert Das Z so we're going to modify the brightness and invert the color if is active if we save that you can see that now it is completely white going below this div we can create a P tag and we can render the item. label but let's style it a bit by giving it a class name we can use the CN property one more time here all classes will have a sidebar label but dynamically we're going to give it important text white to overwrite it only if it is active and now if we expand it you can see that it looks great on desktop devices at least the links do but the logo seems a bit broken so let's fix it if we go up we have our logo here I think I forgot to add this link a flex property that way it will show right next to it and now it's looking great and as soon as we collapse it a bit it will remove the text to allow us to see more of the main content that is great later on right here at the bottom going below this Dynamic part We'll add the information about the user so we can say user here and we'll add some kind of a simple footer right here below the nav for now you cannot see them as they're white right right here user and user but this user and footer we can Implement later on once we actually log our users in with that said the only thing that remains regarding the layout and the sidebar is to figure out what happens on mobile devices when we don't have enough horizontal space well then we have to go back to the layout and instead of just rendering a sidebar we also have to render a mobile navbar so let's do that next below the sidebar I will create a div that div will have a class name of flex size- fo and flex-all within it we can have another div that will have a class name equal to root- layout within it we can render an image which will be our logo so let's do image we we have to import that image from next image give it a source equal to for slash ions logo.svg a width of 30 a height of 30 and an Al tag off menu icon there we go so now we can see something that looks like this and right below it we can render a div inside of which we can render a mobile M navbar so let's create a new component for mobile navbar or mobile na. DSX run RFC in that nav bar we can also accept the user and that will be of a type mobile nav props and we can just call it within this div mobile nav and we can give it a user equal to logged in great and finally this children will go a bit up just one div up right here to fit it better within the content there we go so now we have the logo on the top it's not a menu icon it's a logo and then we have the mobile nav on the right so let's dive into the mobile nav and let's start implementing it to get started with the mobile nav we'll use a shat CN sheet component which extends the dialogue to display content that complements the main content of the screen so it's going to be a button that when you click it opens up a complete new sidebar so let's follow the installation process we can just copy it from the CLI paste it right here MPX shaten UI latest ad sheet we can copy all of the Imports and paste them at the top and we can then copy the usage so let's paste it right Within in this section and there we go let's see how that looks like I'm going to save it and going back to our app we can click open and there we go it opens up it looks a bit weird but don't worry we'll make it look better so what we can do here is give this section A Class name equal to w- for full width and Max dw- 264 pixels within the square brackets you use the square brackets when you want to provide a specific value next we're going to have a sheet and the sheet trigger but the sheet trigger won't simply be a text element rather will render an image right within it which we have to import from next image and we can give it a source equal to for SL ions SL hamburger. SVG alongside a width of about 30 height of about 30 as well an Al tag of menu and a class name of cursor Das pointer so now if we save it you can see this looks more like a menu great now let's move over to sheet content and let's give it a side is equal to left of course this is up to you but for now I want to keep this on the left side and we don't need a sheet sheet header or a sheet title so I'm going to remove that rather directly within the sheet content we want to render our link and this will be the same link that we have in our navigation bar so let's import it from next link and instead of just putting it here let's basically copy everything we have from the navigation bar or rather the sidebar so everything included within the nav bar so starting from within the nav all the way before the nav ends that's going to be right here and we can just paste it within the sheet content and let's make sure to indent it properly there we go let's also fix a few of these issues such as importing the sidebar links and we also have to import the path name we know how to do that you can just go here and say const path name is equal to use path name coming from next navigation and do we need anything else yeah we need CN coming from lib utils and I think that's it let's see oh yeah now we need to turn our component into a client component because we're using some hooks so let's go here and say use client there we go now if we click it you'll be able to see something that resembles our sidebar but let's go ahead and style this sheet content by giving it a class name equal to border dnone as well as BG white there we go that's better this link won't have the margin bottom of 12 we don't need it here it will have cursor pointer Flex item Center we can do Gap one and padding X of four to create some spacing right below it we have the image that's the logo and we can remove this class name right here and then we have this H1 where we can give it a text of 26 we can also give it a font Das IBM dx- serif font D bold and text- black-1 of course if we spell it properly now let's open up the menu and there we go it looks great next we'll wrap all of our sidebar links within a div so right below this link let's create a div with a class name equal to mobile nv- sheet and now within that div we can put something known as sheet close coming from components UI this will be as child so it's a child of the sheet and within it we can have our nav that nav will have a class name equal to flex h- full flex-all gap of six padding top of 16 and text- white and within it we can render all of the sidebar links so let's copy this entire thing and let's put it within this nav right here and let's indented properly one two there we go that's better and basically what this sheet close means is that whenever we click somewhere on it we're going to close it okay so we also want to make these elements within it sheet close so let's wrap this link with sheet close we're going to also give it as child and we're going to give it a key as we're mapping overhead of item. route and now we can put this link within that sheet close so now if I go ahead and click on the home for example it's going to close it because we don't want to click here and then having to close it every time we want to make sure that it navigates immediately let's see if we have to style our link right here instead of a sidebar link we can say this will be a mobile nav Das sheet underscore close and it will also have a w full and save so now it's going to look a bit different in this case we don't need this div that's wrapping this image rather we'll just give it a width of about 20 height of about 20 and save it and then we have our P tag to which we'll give a class of text -16 font D semi bold text- black-2 and then text white if we are active and now we have a beautiful sidebar as before right here within the nav we'll render some user data once we actually have our user and then below the sheet close we'll render our footer as well so that's going to come later on you can see it here great so now if you go here and if you click on my Banks it's going to close the sidebar if you close it that works too so with that now we have a beautiful mobile nav as well as a full sidebar but of course what's missing to make it complete is the right sidebar which adds a lot of color and character to our application it also adds a lot of personalization as here we can display the user data some kind of a background and even cards and budgets associated with our accounts so let's finalize the layout of the homepage by implementing the right sidebar we can do that by exiting the mobile nav and it's not going to be within the layout and the question is why well because none of the other Pages use that right sidebar it's going to be used only on the homepage which means that it's not going to be within the layout rather it will be within the root page itself so going below the header later on here we'll have recent transactions and then exiting that main part we're going to have the right sidebar so let's immediately create a component for it components right sidebar. TSX run RFC and then just import it here as right sidebar that's great to it we can pass some similar props such as let's do user is equal to logged in let's also pass transactions which will be equal to some kind of an array of transactions and then Banks which will also be equal to an array of some banks so now that they're passing that let's go into the right sidebar and let's accept those props at the top by destructuring the user transactions as well as Banks that's going to be of a type right sidebar props and I'm going to collapse our view so we can see how it looks like on mobile of course on mobile it should be hidden so the first thing we have to do is we can turn this into an HTML 5 semantic aside tag which means it's on the side and by itself this didn't remove it see if I say it right it's still there but if I give it a class name of right- sidebar it's gone and that's because this right sidebar if we search for it in the classes is applying a no no scroll bar but then most importantly it hides it on smaller devices and then only on larger devices it actually shows it we can see that right here m-w of 300 then it gives it a minwidth otherwise it's going to be hidden and then when it starts showing it's actually on in with 1,280 because then we switch from hidden to display Flex so let's expand our browser so we can see it let's see I'm going to about here there we go and now it jumps out so let's continue with the right sidebar by giving it a section with a class name equal to flex flex-all and padding bottom of a right within it we can have a self-closing div with a class name equal to profile Dash banner and immediately we get this nice looking background once again if you search for this class you'll be able to see how we're doing that it's coming from globals we give it a height a width and we apply this BG background mesh which adds a background image of a URL that is within our assets right below it we can start framing a div for our profile by giving it a class name of profile and then within it we can have a div with a class name equal to profile-img within that we can have a span that will try to render the first name of the user let me see if I have given my user a first name here it looks like I have so we can render the user. first name and specifically we're going to render zero only the first character of the first name that's going to be for the image here so let's make it a bit bigger by giving it a class name equal to text- 5 Excel font Das bold and text- blue 500 going below this span and Below one more div we can create a div with a class name equal to profile Das details and then within it we can create an H1 that will render the user. first name and we can also do user. last name as this here is the full profile so let me just add it here last name is going to be JSM there we go let's style this H1 by giving it a class name equal to profile Das name and right below it we can render a P tag that will render a class name equal to profile D email and within there we can render the user. email of course we have to go here and actually pass the email I'm going to do contact at JS mastery. proo for now all of this is static but as soon as we Implement account creation we'll pull this data for real and now we can start focusing on the second section from our sidebar which will be below our first section and it will be a section about all of our current Banks so let's give this section A Class name of banks with a div of class name flex w-o and justify between and then below that H2 that will have a class name of header -2 and it will say my Banks right below it we can have a link which we need to import from next link and it will have an href equal to forward slash with a class name equal to flex in the gap of two right now we are recreating this plus and add bank and then later on we'll focus on this beautiful card component and we'll build it from scratch so this link will render an image which has to come from next image of course it will have a source equal to SL ions SL plus. SVG with a width of about 20 a height of about 20 and an ALT of plus there we go that's better and let's also give it a text to explain what it is H2 that will have a class name equal to text D14 font D semi bold and text- gray- 600 that will say something like add Bank there we go that's great finally for each one of our banks we can add a new card so let's do just that let's go below this div and let's map over the banks if we have any of course by saying if Banks question mark. length is greater than zero so if we have any then render a div let's do some positioning within that div by giving it a class name of relative Flex Flex D1 flexx call items Das Center justify Dash Center and a gap of five within it we can have another div that will have a class name of relative and Z index of 10 and within it we want to render our bank card one then we can go below this inner div and say if we have bags one so if we have two different cards then render an additional div okay and this div will have a class name of absolute right zero but top 8 Z of zero and W of 90% and it will say bank card to at the moment there are no bank cards and that's because we're passing a prop of banks empty array but if we instead create two empty objects you can see bank card one and bank card 2 which is moved a bit what we're going for here is this card layout where one card will be moved a bit from the other so we can show that we have multiple now each one of our cards in the future will have to have a lot of data the first name numbers company type of the card and so much more but for now we're going to keep it empty first things first let's create an actual bank component by going to components and saying Bank card. TSX where we can run ource and we can import it right here bank card coming from that slbank card and we're going to have a second one to we do have to pass some props to it so here we can say key is equal to Banks z. dollar sign ID account will be equal to Banks zero because this is the first bank account username will be equal to a template string of user. first name and then also user. last name and show balance in this case will be false we can also replicate all of this over to the second bank card this time it will be Banks one ID Banks One account same username and show balance to fals so now we can dive into the bank card and start implementing its UI this is an exciting one and as I said we'll do it all from scratch to teach you how we can implement this interesting card layout to get started let's first accept all of the props such as the account username and show balance which by default can be said to true but we're setting it to false otherwise and we can say that this is of a type card credit card props let's give it a class name equal to flex and flex-all to start creating the layout and then we can make the entire card clickable yes it will be a link which will point to more credit card details so let's import link from next link and let's give it an href later on we're going to make it point to the account details and a class name of Bank Dash card so already this created this rectangular layout and again if you're wondering about specific classes just search for it and check it out here card is basically G giving it a specific height of 190 full width and the max width we're rounding up the corners a bit giving it white borders and giving it this background gradient it can be just fully blue if you wanted to but this is okay and then we're applying some shadows and background blurs this was mostly generated by Chad GPT within this link we can create another div with a class name equal to bank- cardor content okay looks a bit weird for now within it we can have a div and within that div we'll have an H1 which will have a class name equal to text D16 font D semi bold and text- white and it can render the account. name right now I don't think we have it so it will just be under defined but later on we will have it for now maybe we can say something like your name here in case you don't have it there we go that's good or maybe even better we can make it equal to username right if we don't have the account name coming from the database yeah that's good below the H1 we can render the P tag which will have a class name equal to font D IBM DPX dsif font Das black and text- white within here we can render the current balance of the account by saying format amount this is the utility function and then we can pass the account do current balance of course we don't have anything yet so it's going to say Nan what we could do is just pass some of the information to this account let's see we're passing Banks zero and Banks this entire time is an empty array and maybe we give each one of these accounts a current balance of let's do 1 2 3 50 and now we can see that this amount is directly reflected on the card we can also do it here let's do 500 great so now we can see it there going back to the bank card going below this P tag and below the div we can create the r article article is similar to a div basically the same but it says that we'll show some data in there we can have a class name to flex flex-all and gap of two within it we can create another div that will have a class name equal to flex and justify Dash between and within this div we can have an H1 which will render the user name you can see it there let's style it a bit by giving it a class name equal to text -12 font D semi bold and text- white that's good we can also duplicate that H1 change it to H2 and this time we can render some asterisks which are basically numbers which we can enter near a card that's going to look like this below that div we can also render a P tag that will have a class name equal to text -14 font Das semi bold tracking of 1.1 pixels this is the space between the characters in text- white and here we can just put three times of four numbers of stars 1 two 3 4 1 2 3 4 and 1 two 3 4 this is basically a bank account there we go and we can also then create a span element with a class name of text 16 where we can render The account. Mask so this will be those last numbers of the account right now we don't have it but we'll fix it soon next we can go below the article and below the div and we can render another div with a class last name equal to bank- cardor ion where we can render an image we can import the image from next image give it a source equal to slash ions slay pass. SVG with a capital P with a width of 20 height of 24 and an Al tag of pay that's going to give it that second part right here and we can also render an image right below it that's going to be an image with a source equal to/ icons slm mastercard. SVG we can give it a width of 45 a height of 32 and we can say alt of MasterCard of course you can use some other provider right now it's hard to see it but if I expand it a bit more you should be able to see it on the second card don't worry we're going to fix the layout later on and make it look much closer to what we have here okay finally we can go below the div and render one last image that will have a source of icons lines.png with a width of about 316 and a height of about 190 with an Al tag of lines and class name of absolute top zero left zero and you have to start with a forward slash for icons here that's going to give it some lines right here on the right side as each card has to have some details on it later on right below will also add the ability to immediately copy the card numbers for now this is okay now let's fix the layout of the card I think we can fix it just by making the card a bit wider right now it looks like it's lacking width making it more of this boxy shape whereas if we add more width it's going to look more rectangular and I think that's because we're using these asterisks instead of real circles so you can simply Google black circle symbol text and you can either use this decimal value or you can just copy this symbol right here going back to the code we can replace 1 2 3 4 1 2 3 4 1 2 3 4 and we don't yet have the count mask and these are basically the last four characters so for now we can just type them in right here as a regular string and remove the dollar sign we can also replace these two with those circles it's going to look much better and if we go back now this is looking more like a real card we can also add some left margin to this Master Card Icon by going here and giving it a class name equal to margin left of something like five there we go that's better so now we have two actual cards as you can see the layout is starting to resemble more and more the final layout that we are going for that looks like this let's compare it current final current final we are getting there the only thing that we're missing for now are the recent transactions and we'll do that very soon but for that we'll have to connect our account so before we go ahead and connect account what do you say that we Implement full routing for our application so links to my Banks transaction history and more doing that within nextjs is super simple as we just have to go into the sidebar which is right here and then go into the sidebar links and immediately we can see which routes do we need we need my Banks transaction history and payment transfer for now so let's Implement these three the way you do it is you go to the app you go to the root and create a new folder with that name so that's going to be my banks with a new page. DSX where you can run rafc and you can of course rename it to my Banks after that we can do transaction Dash history so that's another folder transaction dtory and we can create a new page. ttsx where you can say rafc and call it transaction history and then the last one is payment Das transfer so that's going to be a new folder payment Das transfer that's going to have a page. TSX where we can run RFC and rename it to transfer now if we go back to application we can go to my Banks transaction history as well as transfer so the complete layout of our application has been implemented alongside some starting parts of the homepage such as the header the bank accounts and the right sidebar and don't forget we also made it work for mobile devices so once you click on your special nav bar a new drawer will appear and you can paginate between different pages with that in mind let's not forget to stick with what we said and that is to push and commit often so in this case we can use the built-in GUI for Source control and in this case I'm using co-pilot to generate a quick message let's see if it's good fix CPO in toal Balance props no that's not as descriptive we can say something like implement the complete layout and commit and push now for the last time I'm going to repeat how you can make use of these commits you just go here you go into this commit and you can see all of the code changes that we implemented within this specific commit but then you can also click browse files to explore the state of the code base at this point in time how cool is that so finally going back to our app and navigating manually to slash sign in we are ready to start implementing o to get started with a signin page let's navigate over to page sign in by the way I did this by pressing command or alt and then p and then that opens up the file explorer where you can just start typing the page you want to open and press enter much quicker than going here and then searching for it and then finding it right right so command or alt P type in what you want to do and press enter just another one of many pro tips which will come throughout this video let's turn this into a section with a class name of flex Das Center size- full and Max Das small padding X of six so now it's nicely centered and we're going to do another very cool thing here we won't be creating our form within here as then we wouldn't be able to reuse it across different pages specifically across sign up so what we're going to do is create a new component called oth form. TSX run RFC and then we can use that odd form right within here coming from OD form and we can pass it a single prop type of sign in and we can also reuse it on the second page so now if we go into the OD form and if we accept that type which will be of a type string like this we can render the form depending on what we have there so let's do just type for now as you can see it says sign in right here on top and now if I go to the sign up page and copy everything I have in sign in but this time I will change the page name to sign up and I will change the type to sign up as well and now if we go from sign in to forward SL sign up you can see that it changes and we can now navigate between the two which later on will mean that you can have two completely different forms for two of the same Pages by using this reusable OD form component great with that in mind we can dive into the OD form and start implementing it our o form will be a section with a class name equal to o- form right within it we're going to have a header component and that header will have a class name equal to flex flex-all Gap of five and on medium devices gap of eight within it we can render our first link and I think this is the same link coming from the navbar so let's go to our navbar or mobile nav and we can find our Horizon logo right here there we go a link with the image that says Horizon so we're reusing this multiple times we can paste it here let's import link from next link and image from next image and let's see if we need to style it a bit cursor pointer Flex item Center Gap one in this case we don't need padding X withd and height or okay text 26 this is looking good yeah I think we're good now moving below the link we can render a div that will have a class name of flex flex-all gap of one and on medium devices gap of three within it we can render another H1 that will see if we already have access to the user and that's something we'll have to figure out on our own so right at the top we can create a new use State snippet within which we'll save our user data so user set user the start equal to null and let's properly spell it here and let's let's import use state from react okay so at the start the user is null so if we have a user then we can say Link account referring to the bank account and else we can check it the type and if the type is triple equal to sign in then we can say sign in else we can say sign up and since we're using use State you know what we have to do we have to turn this into a use client component there we go and now it says sign in let's style it a bit by giving it a class name equal to text- 24 on large devices text -36 font D semi bold and text- gray- 900 there we go that's good below it we can render a p tag with a class name equal to text -16 font dormal text- gray D600 and we're going to do another tary operator if we have a user we'll say something like link your account to get started else will say something like please enter your details there we go that's looking good and now we can go below the header and here we can check if we have access to the user so if we have already authenticated if we have then we're going to return a div with a class name equal to flex flex-all gap of four and later on here we're going to render a played link component to link our bank account for now we can leave it empty and if we're not yet authenticated then we can render an empty react fragment inside of which we'll have our form and of course we'll be using a shat CN form ah forms they're tricky am I right even Shaden says so but they are one of the most common things you'll build in a web application but also one of the most complex well-designed HTML forms are well structured and semantically correct easy to use and navigate around using your keyword as well do you know that feeling when you try to submit your form using an Enter key and it doesn't do anything well yes most developers don't build proper forms but you you'll learn how to do them properly they should also be accessible with proper area attributes and labels have support for client and service validation and of course they should be well styled and consistent with the rest of the application so by using shat CN form you're also opting in to use react hook form one of the best packages to build proper react forms and Zod the best library for form validation so let's look into the features of our form the form component itself will be a wrapper around react hook form Library providing a few things composable components for building forms a form field component for building control form Fields form validation using Zod handling accessibility and error messages out of the box using unique IDs correct ARA labels built with rics components and it's fully customizable giving you full control over the markup and styling so let's study the anatomy of a form the form component is a general wrapper around multiple form Fields each form field is like an input that has its controls names and then finally you can choose how to render it in most cases you'll be rendering a form input with a label a control description and a message here is a full example here we initialize a form give it a control a name render a form label for the username and an input with a placeholder form description and a message now let's actually use said first step within the installation is to add it to our components so let's just do MPX shaty and UI latest ad form and we can create a form schema so let's copy what we have here and paste it at the top of this file in this case we're working on some kind of an O form but you can use this chatsi and form tutorial to build any kind of forms let's paste what we copied we already have used client at the top so we don't need it and of course it's important to mention that every single form in the browser will always have to be used client because you have keyboard and mouse events such as onsubmit on key press and more so for that reason if you're in next GS the pages in which we use the form such as the sign in or the sign up typically will be server side and then the actual OD form component will be client side side great so let's see how we can define a type of our form using Zod Zod is a very simple and straightforward form validation tool allowing us to choose which types of fields we want within our form schema defining the type of that field and the minimum and maximum amount of characters if you press a DOT there's also many more different types of form inputs that you want to have and you can do much more indepth valid ation if you want to for now we're going to stick with this the second step we have to do is Define a form so let's just copy the Imports right here at the top we're importing a Zod resolver and a use form from react hook form we already have the form schema but in this case they are kind of beefing it up a bit by adding custom validation message which you can do so if you break one of the rules as the second parameter of that specific rule within Zod you can apply an object with a message that will be presented to the user if that specific rule fails pretty handy right next we have to Define our form within our application and Define an onsubmit so let's copy this and let's put it directly within our form component so first we Define our form by saying const form is equal to to use form coming from react hook form if you're using typescript you can stick with these types as well this ensures that you always know exactly which Fields does your form contain depending on that form schema we have created now that long ago and it also allows you to provide default values such as username is an empty string next you have to define a submit Handler it's a simple function that does something with the form values once you submit it and you always know that it will be typed safe and validated now since form field is using a controlled component you need to provide a default value for that field as we have done right here the third step is to build our form we can now use the form components to build a form first things first we have to import them so let's copy all of the Imports and paste them right here you'll notice that we had previously installed the button and the form but we haven't yet installed the input which is a separate shaten component so if you haven't already you need to do MPX shaten - UI add latest add you can add a form button and input and that will install them in this case I already have some so it's going to ask me to rewrite which is okay now that everything is installed we can copy the usage of the form right here so let me just copy it all the way through the end and let's paste it right here where our form should go there we go and let's indent it properly great so as you can see the form component this one right here coming from shaten to which we pass the form object from react hook form is just a wrapper for a typical HTML form it has an onsubmit Handler that calls our function onsubmit and it has a single form field with a control name and we render a single form item with a label of username we render the input and description and the message so going back to our sample application you can see how nice this looks like it is very simple and minimalistic we get this label so we know what we're typing into we have this chat CN we have a form description we have an input with a placeholder and even a form description if we still don't know what we have to type in and then a button to submit it in this case if we click submit you can see that a username must be at least two characters which is this custom error message that we used before in this case we won't be needing a username so let me show you how we can modify this to suit our needs and then we can even create a second form field first of all we'll change the name to email in this case where we have a form item and this time let's start from scratch so I can properly teach you how to create a proper form item within render I'll render a div with a class name equal to form item this is just a custom tailin CSS class to make it look a bit better we can then render a form label right within it that will say something like email and we can give it a class name equal to form label there we go right below the label we can have another div with a class name equal to flex w-o and flex-all and here we can render a form control within the form control we can have an input that input will have a placeholder equal to enter your email there we go as simple as possible let's also give it a class name of input Das class and a pretty cool thing about this input is you can provide any kind of taleban class names directly within here and very important you have to spread all of the properties of the field for this to work and the field you're getting here this is how react hook form works and you have to follow some rules finally below the form control we have the form message and we can give it a class name equal to form Das message now you can notice that immediately the use of typescript Zod and react hook form is saving us from making a mistake this red squiggly line says that type email is not assignable to type username as that is the only property we have in our for now so what we have to do is do the default value of email and also change the validation here from username to email and we'll do some custom validation here by saying z. string and then email so this will ensure that we entered the email and you can see how simple that was we don't have to do any special regular Expressions to validate that rather if we just type something it will say invalid email scrolling down we can maybe give this form message right here a margin top of two to divide it a bit there we go that's better below the email we'll also need a password and now there's two different things you can do you can just take this form field select it all the way until the end which is here and then duplicate it right below this will allow you to to maybe change this name to password change the label to password as well change the input to enter your password and give it a type of password so things get hidden and save it and that's it you get a second field another alternative you can do especially if you have more inputs is you can extract this form field into a new custom component and then you can reuse it multiple times within your code I'm not going to fully show you how to do it but I will leave that open as an exercise for you if you want to practice some component reusability you would go into the components and create a new let's call it custom input. TSX you would run rafc and you would paste this input that you copied that's the idea let's also indent it like this now now you would have to pass some things as props such as first of all the form and you would have to import all the things from chaten like form label form control and the input as well and then the key thing is you have to pass additional properties which are different every time so for example this name will be different for every input so you pass it as a prop and then you use the name here here the label will also be different so you pass the label as a prop right here as well so this will be a label the placeholder will also be different so we can pass the placeholder to and we can use this one here placeholder that's good and the form message I think is the same but we just didn't import it so that's it some things will be different and then you can now call this custom input right within your application let's call it here custom input you can call it two times and you have to provide all of these things form is equal to form name is equal to well first time it's going to be username or just like this username label will be equal to username and placeholder will be enter your username and now what you get is a beautiful oneliner like this that acts as your input and you can even duplicate it and then modify password here and enter your password and you have two separate inputs in two lines instead of repeating this every single time so pause this video and try to implement these two form fields we have created but using this custom input reusable component so I hope you'll pause it right now and then unpause it for the solution in three two 1 okay how did you do well initially I didn't want to provide you with a complete solution but I thought you know what I really want to make sure that you get this right as it's very important so in this case let's first indent this properly there must be a quicker way but for now I'm just going to select every starting line and then I will move it by the way I'm holding the Windows key or option I believe on Mac selecting multiple and now we can move it all back like this there we go now since we're using typescript we'll have to choose a custom interface by saying something like interface custom input and then we can choose different props we have such as form is of a type well let's see what the form is by going all the way here I think we can import the type from react hook form by saying import form from react Das hook- form let's see if this will work uh we need to pass some additional properties to it we can maybe add type off form this seems to be okay for now we'll see how it goes in the future let's also do a name of a type string we have to do a label of a type string as well and we can do a placeholder of a type string now we can say this custom input is of a type custom input and now everything is good besides this form. control it's complaining that we have a wrong type so let's try to approach it the other way it looks like we don't have to pass the whole form as we only need a control here so let's first of all modify that instead of accepting the form let's just accept the control itself allowing us to control each one of these inputs and when we're calling it right here we can just pass the control equal to form. control okay that is good and now we have to figure out the proper type so I think that react hook form also has a type for control yep there we go control and we can rename it from form to control here too but this control does require some additional properties rather it requires everything we have already passed to our form right here and that is this part right here Z infer type off form schema this this will save us from passing some wrong properties so here we can expand it with z. infer form schema and of course you can immediately notice that we need to import Zod right here and we also need access to the complete form schema so whatever you have here we also have to have it within a custom input so that might be the perfect opportunity to extract it and move it into utils or into any other separate file in this case I'm going to go into lib and then utils and then right at the bottom I'm going to say const form schema I'm going to export it in this case this is the off form schema I will import Z right here from Zod it will have an email as well as a password of a type z. string and we can do a men of eight characters now going back to our OD form instead of saying form schema three times we can just say OD form schema and import it from lib utils here here and here we can add a default value for the password of an empty string and in the custom input we can also say a form schema and we can directly import it from there so we know it's always the same and there you have it instead of two we have four inputs now allowing us to delete these long ones that we have here this entire form field for the email which we can delete and we can also delete the second form field for the password and we end up with a form that has two single line form inputs let's indent it properly space out and doesn't this make so much more sense than what we had before of course let's change this label to a capital u and this password to capital P and more or less that's it the validation should still be there let's see if it is though it's complaining about a name saying that it cannot be email or password even though here we have email and password oh but I have username here yeah that's good that Zod saved us there actually we want to have email here enter your email and then we have enter your password that's good invalid email password is required to but now this name is giving us an issue saying that type string is not assignable to type either email or password so that's happening because here under name I said it can be any kind of string but it knows for a fact that it has to be one of these things right here either email or password and this is pretty cool because it's trying to keep us safe and keep us away from making mistakes such as misspelling those names so sure we could solve it like this where we can say that the name explicitly is either email or password and I think this would work yep it does so now even if we go here and if we miss spell it something like email right here immediately it says hey did you mean email pretty cool right but a problem with this is if we add another input right here that will maybe be let's say email password and then username if we add the username here and if we also add the username within our odd form schema like this that would be good right but then we have to go into the input and also add it here at the end and that's going to be never ending we want to have one single source of Truth and that is our o form schema so we have to somehow figure out how to extract values directly from it and I think we can do that by using the field path type coming from react hook form and to it we can pass the exact same z. infer OD form schema this way it will always know exactly which Fields do we have take a look at this it knows that it can either be email password or username because we have added it right here into the odd form schema if I remove it it knows exactly what it is this is the power of react hook form typescript Zod and Shad CN all brought together to create scalable and Powerful forms now let's remove this third custom input from here and let's see if we're missing something else we have the form label with a custom label we have a form input right here form control that's looking good and then a form message yeah I think this is it this is all that we need to have proper forms with reusable custom inputs and now if we start typing email oh it looks like it's a password so what we have to do is go back and just make this input not a password oh and I'm glad this happened because I can show you how to make your custom input accommodate to any future changes in your application for example in most cases this will have to be a type of text right for the email but for the password it needs to be a password so we can either use one of the existing properties like a name or you can add an additional Boolean value like password right I think in this case the name will be enough so we can just add a check right here and say if name is triple equal to password then the field will be password else it will be text now if we save this you can see email looks good we can type something in and you can see that it's going to do full validation for email so we have to do something like contact adjs mastery. proo and then for the password you can see string must contain at least eight characters one 2 3 1 2 3 1 2 3 that's not my real password and there we go we can actually submit the form and once we submitt it what happens well we're going to call our onsubmit function which will consal log the values since forms our client side we won't see the conso log on the server rather if I click it once again you can see email and password right here perfect and this my friend was a master class on creating forms using shat CN react hook form Zod and even taking you a step further by teaching you how to create custom inputs and as a bonus I want to teach you how to make the same form work for both sign in and sign up first of all let's modify the button a bit and add a link so we can quickly switch between the two let's give this button a class name equal to form D BTN there we go that's better and let's also Implement a loading State as I want to teach you how to make truly responsive forms we can do that by creating a new use State snippet and let's call it is loading set is loading at the start set to false as we start the submit Handler here we want to set is loading to true as we want to do some actions with form values and then at the end we want to set is loading to false as we're done with those actions of course here we're just cons logging it so it's going to take just a millisecond but usually you're doing some asynchronous actions here so it will actually load for some time so within the button we can check if we are loading so if is loading then we want to render a react fragment that will render a loader to coming from Lucid react I believe this is built in with chaten we can give it a size equal to 20 as well as a class name equal to animate Das Spin and this is also built in after that we can create an empty space by saying dollar sign mbsb and then we can say loading do dot if we're not loading we want to ask our is the type equal to sign- in and if it is then say sign in else say sign up so if we save it now it says sign in we can also make this capitalized there we go and let's quickly simulate the loading so I can show you how that looks like so here we can say is loading is true and you can see how that would look like now this is not only important for aesthetic reasons it's also important if you're submitting a form or creating something in the database based off of that form submission you want to set this button to be disabled and it will be disabled if the is loading is true that way as you can see a user won't be able to press it multiple times and spam your database great so now let's go back to bringing it to false and as you saw all of these little things make your forms stand out now that we have a beautiful button let's go below the form and create a footer that footer will have a class name equal to flex justify Dash Center and a gap of one and we can do a p Tag 2 inside of which we can check the type and if the type is equal equal to sign in then we can do something like this don't have an account question mark else we can say something like already have an account question mark so this way we can nicely switch between sign in and sign up of course by adding a link right below it that link can have an href which is also Dynamic depending on the time type so if the type is sign in then we can make it go to for slash sign up else we can make it go to forward slash sign in and once again depending on that type we can copy it we can make the label of that link be a bit different we can say something like sign up and here we can say sign in there we go don't have an account sign up sign in let's also style it a bit by giving this P tag a class name of text -14 font dormal and text- gray- 600 and we can give this link a class name equal to form dlink there we go that's better and also as this text is centered let's also wrap our button in a div looking like this there we go and this div will have a class name equal to flex Flex Das Co and a gap of four that's going to make it full width and now this is looking like a proper form now the second thing we can do is Click sign up which will immediately modify the URL path and therefore change the page we're on so now we can just switch between the two and you can see the buttons changing but the input Fields remain the same and typically on signup forms you'll have many more Links at least one more for the username but in case of this banking app which is the perfect example for practicing forms here we have some more Fields so let's see how we would implement this so that it still stays as part of a single form because one more time remember both the sign-in page and the the signup page use the same form but we're passing a different type and based off of this type we'll be able to render different inputs so starting off right at the top of the form we can create a new Turner operator and check if type is triple equal to sign up and only in that case we can render a react fragment with some additional inputs so let's immediately add a cut custom input we now know how to do that and we'll need it for the first name last name address State Postal date of bird SSN and I think that's it so what we can do is go ahead and copy it paste it and just modify the parameters the control will be the same and in this case the label for the first input is the first name so let's say first name the name can be just first name like this for now we'll get an error because it doesn't correspond to any of our existing types but soon enough we'll add new types and placeholder can be enter your first name we can duplicate that input below we can have one for last name we're going to also say here last name let's also duplicate one and add one for the address so that's going to be address and the label will be address enter your specific address that's the placeholder we can see it in the design then we have the state so that's going to be State and State and we can say something like placeholder example and Y after that we have the postal code so that's going to be postal code with a label of postal code and an example of 11101 let's do another one right here which is going to be a date of birth for the label typically that's shortened for do date of birth but we can of course use the full name date of birth example is going to be well not an example it's y y y y this is the year format month month and then date date and these are all the additional fields that we need for our sign up so going back to our app and reloading it and switching over to sign up you'll be able to see all of these new fields we have just added now one thing we have to do is also implement the Zod validation for all of these states so let's head over to utils and we can add it here I think I am missing one field from the design which is the SSN so if I check it out here after the date of birth we have the social security number as this is a banking application so I will just duplicate it one more time do the SSN label will be SSN as well and then placeholder will be example of 1 2 3 4 there we go so now we have all of these fields we can copy all of their names by holding the option or the Windows key then copying it and we can now paste it within utils o form schema and we know that each one needs to start with Z z. something to do the validation in this case most of these will be string so z. string and we can use like a men of three characters that's good and add a comma now we can look into them and maybe fix them bit if we need to I'm going to put the email and password at the bottom as they're also for the sign in so I'm going to say Here sign in and these will be for sign up or no technically these will be for both right both sign up and sign in so let's see first name last name minimum of three characters we can also do email has to be email we have the address proper name would be to call it address one so let's do that address one and it's going to be a Max of 50 again this is just ensuring that we do proper validation now State specifically will have two characters so do Max we can do two and I think we can also do Min two and that Max two so this is the specific number postal code will have a Min of three and a Max of six I believe depending on the country date of birth me three and then SSN like this this this is good so we just have to change the name right here for the address to address one and now I want to show you something important if you try to submit this form of course you won't be able to because all of these fields are required but what happens if you go to sign in and you enter both of these fields and you enter them properly like an email and you also enter a password you won't be able to sign in because behind the scenes it will try to validate the sign up form too and it won't let you pass so for that reason we have to turn this OD form schema into a function that accepts the type we're trying to validate so here we can accept a type and then return this object and then based of this type we can then either make it optional or not so let's select all of these that only appear on sign up and then say if type is triple equal to sign in then we want to make it z. string do optional okay else we're going to make it whatever else we made it before now I know I've significantly expanded this but it still fits in one line and it's optional if a type which is of a type string is sign in so that way it should let you submit your form a of course for this to work we now have to modify the way that we import our o form schema by saying that our form schema is equal to and now we call the OD form schema as a function and pass in the type into it and now instead of referring to odd form schema here we can just use form schema which is going to make it work and also here I hope this wasn't too overwhelming so we just had to turn this into a function so we can pass the type into it so we can then generate a real Z schema based on the type we also have to do this within the custom input so let's go there and at the top we can say const form schema is equal to we call off form schema and then we pass a specific type and then we can pass sign up in this cas case because we want to use all of the fields so we just do it like this and now it's okay and now as you can see our inputs are not complaining going back here our form is looking good but it's not exactly the same as on the design as you can see this is how it should look like some inputs should take half the width and some should take the full width so what we can do is we can wrap those inputs that need to be together in a div for example the first name and the last name like this and we can give them a class name equal to flex and a gap of four and that's it how simple that was let's see which ones have to be together as well I think it's going to be the state and the postal code so let's go to State and postal code and we can copy this div State and postal code and close this div right here and indent it properly there we go and finally date of birth and SSN so again absolutely the same thing we have a div and we properly close it and this now looks much better than before as it feels like we can actually do this in one go it's not too overwhelming again complete validation Works incredibly well and it's not only required but if you start typing you can see that it will request you to be at least a specific number of characters or at most a specific number of characters so all of this has very very good validation and we can also switch to sign in which now should work properly and should submit if we only enter two Fields as the others are optional so let's give it a test for sign in I'm going to open up the inspect element and enter my email contact jm.pro 123123123 you can see it submits and we can go to sign up I will try to enter some stuff here I'll try to make it as random as possible but we still have to make sure to respect the validation so let me do the year as well that's going to be this we're going to have this as well email and password and we have submitted the entire form perfect so with this bonus exercise you have now learned how powerful it is to create custom reusable components and you also saw on a real example that it saved us writing hundreds and hundreds of lines because if we didn't have this custom input which now fits on a single screen even though I'm zoomed in a lot right imagine if I wasn't zoomed in you would be able to see the entire form right here in a couple of lines and if we didn't have that you would have to write from line 20 to line 40 which means 20 lines for each one of these inputs instead of a single line and that concludes the lesson as well as the bonus exercise on forms react hook form and zad validation so now you know how to make the best best forms out there that are scalable and with proper validation great work now we can start figuring out what we want to happen once the user submits this form for that I will expand this onsubmit a bit and make it into an es6 arrow function like this and I will also make it asynchronous by adding the async keyword right here at the start as I said we want to set its loading to true but now instead of Simply cons logging the data we want to do something asynchronously we want to submit that data somewhere so for that reason I'm going to open up a new try and catch block actually it will have a finally Clause too this Clause allows you to turn off the loading no matter whether we succeed or fail whatever happens we want to stop the loading and allow the user to try again and in the catch we can simply consel log the error but in the try is where the magic happens here we want to sign up with aight so create a new account on there and also create a played link token so we can start linking our bank account first things first we have to figure out if we're signing up or signing in so we can do a type and if type is sign Dash up in that case we can do something else if type is triple equal to sign in we can do something else first we have to form the user data in the right format to pass it over to aite and play so right here within signup we can say const user data is equal to and we can start forming the object in the right way for example we can start with the first name and make that equal to data. First name and this data is coming as the first and only parameter to this function which gives us access to all of the values from our input fields and these are the same values that we consol loged not that long ago it contains the email password first name last name address one state postal code date of birth and SSN I think there's one thing missing though in the final deployed version I also have city as played needs the city to be able to link a bank account but thankfully with our existing structure it is so easy to add a city as well we can do it right below the state or below the address one we can give it a name of City label of City placeholder enter your city and of course we have to go to our utils we have to duplicate address one and we can call it City and that's it if we go to sign up you can see we have enter your city right here it's no longer complaining and if we see the user data here now we have the city as well so we don't even have to form this user data object as all of data is already here so the only thing we have to do is say const new user is equal to await sign up and to that we'll pass the data sign's going to start with a lowercase s and once we get this new user we want to set it to the state by saying set user and we will set it to be equal to new user but right at this moment this signup function doesn't yet exist so for now we'll comment it out and sign in is going to be similar we can say const response is equal to a wait sign in and it's also going to be lowercased and for the sign in we only need email equal to data. email and we need a password equal to data. password finally if we get a response back we want to navigate to the homepage if we successfully log in and for that we'll have to get access to the router const Router is equal to use router coming from next navigation make sure to not import it from next router it's next navigation and once you have it we can go here and then say router. push and we want to push to forward slash which is our homepage and since we haven't yet implemented sign in for now I will comment this out there we go we're back so now I hope it's pretty clear what we have to do next we are successfully fetching all the data from our front end or from our form you can say both for the sign in and the sign up but the question is what do we do with that data next and here comes another lesson where I'm going to teach you how to implement server actions when you're working in nextjs and when you have a front-end form such as this one and you want to take the data from that form and pass it over to some kind of a server make an API call or even make modifications to your database in all of these situations we're going to use a concept known as server actions and mutations server actions are asynchronous functions that are executed on the server they can be used in server and client components to handle form submissions and data mutations in nextjs applications a convention for defining server actions is to use the use server directive on top of the file or where you want to use it a convention to be able to use use server actions is to define a used server directive you can place it at the top of an async function to mark that function as a server action or at the top of a separate file to mark all exports of that file as server actions this is an example where you have a server component and defining a single server action notice the used server right here or you can just create a separate actions. TS file and add the use server directive at the top of the file automatically making all of the exports server actions and this is something that we dive into more depth within our ultimate nextjs course but let me teach you how to do it now as well specifically we'll do it for our signin and sign up two separate server actions since we're going to have multiple I prefer to create an additional file for Server actions by going to lib creating a new folder called actions and we're going to create a new file called user. actions. TS so you can also divide them based on their purpose as we learned we have to add use server at the top and we can export a function so export con sign in is equal to an async function typically I like to use a try and catch block for all of these functions as they're asynchronous so we can do a console. error instead of a console log here where we're we're going to print out the error like this and also we can print out the error message and in the try we typically try to do some kind of a im mutation or modify the database or even sometimes make a fetch even though server actions are post actions and some people will say that you cannot make get requests with them you can and I'll show you how later on so this is a typical structure of a server action and we can duplicate it and create one for sign up two and going back to our OD form we can now uncomment what we have previously commented here and import those server actions from lib actions one and two and you can see as we're using tapescript it immediately knows that we have to pass something into it or that we're not getting something out of it so now is the time that we properly accept all of the props into it starting with signup we know we're passing the user data like this and it'll be of a type sign up per Rams and before we can proceed any further with this we'll first have to set up our open-source backend tool of choice aight as we'll use aight here to create a user account so let's do that next upright helps you build secure and scalable apps with databases authentication functions and storage in our app we'll use their Authentication and database functionalities and I chose aite because it's a comprehensive backend as a service solution that is widely appreciated open- sourced and works very well in server side rendering with nextjs so click the special link in the description that will allow you to follow along and see exactly what I'm seeing then click get started and create your account after that you'll be redirected to your dashboard you can see I already created few projects so far and now I'll create a project for our current application let's give it a name and you can start with JSM uncore you can put your name there and then the application you're building so JSM Adrian bank and I'm going to click next next you can choose the region that's closest to you I'll proceed with this one and our project has been created and we are greeted with a getting started guide immediately from here we can copy our project ID and we can create a new file in the root of our directory called EnV that is for environment variables and you can paste your key here and we're going to give it a name I'm going to call it nextore public underscore aite uncore project and just to make sure that we name our environment Keys the same way we can also create a new file called EnV do example and this is used for all people running your application for the first time so that they know which environment variables they have to use you can find a complete list of environment variable names in the description down below they're going to be within the readme of this project so copy it and paste it here in the EnV example as well as within the EnV and then you can just copy the one that you had for the aight project and add it here on top great the second thing we have to extract from aight is the integration with our server so we're going to choose API key and enter our API key name you can really do anything here I'm going to call it JSM uncore bankor node and we can click next here we have to give it access to specific Scopes you can be a bit more picky but in this case I'm just going to select everything as we'll be the only person in control of this API key and I'm going to click create and here you get your API key secret which you can copy and you can paste it right here under app right secret next we can go back to our overview here now the project is initialized and as I said we want to use two of Appice functionalities oth and databases let's start with oth as we have already implemented frontend Pages for it regarding o everything works out of the box but let's quickly explore it within settings you can see different o methods available we'll be working with email and password but we also have magic URL Anonymous JW token phone email OTP and even team invites alongside a lot of O OD to Providers anything you might need but once we have our user we have to connect Ed to a collection in our database so that's the first thing we'll do within here let's go to databases and create a new database we can enter a database name I'm just going to do Bank in this case and click create immediately you'll be given a bank ID so let's paste it under aight database ID and then we have to create our first collection within this database I will call it users and click create immediately you will be given the ID of that collection so we can paste it here under user collection ID and in this case I don't think we'll need the item collection so you can remove that but we do need a bank collection and a transaction collection so let's also create those two and extract their IDs we can do that by going back creating a second collection let's call it transactions click create copy its ID and paste it make sure that it is right here transactions collection and then we have a bank so let's go back and create another collection let's call it Banks and click create we can also extract the ID and paste it here as you can see we have most of the needed ight environment Keys now within the users colle ction we have to Define how a user will look like by giving it its attributes so let's create them one by one the first attribute will be email so we can just call it email all of them will be required and you can just click create the second attribute will be the user ID and it will be of a type string and we can give it a size of 2,000 that should be enough for any kind of user ID we can also keep it to 2000 for all the other string properties and we're going to make it required and click create now we're going to have some other attributes which we haven't talked about too much yet it's also going to be if a type string and the key will be Dua customer URL okay so what is this DW a let's explain that a bit dalla is an ADD addition to plate and you can think of it like o for adding bank accounts it will allow us to partner with different bank accounts and connect banking details to our account that's all that you need to know for now later on we'll dive deeper into it so we need a customer URL let's also do 2,000 and let's make it required alongside the Dua customer uh URL we'll also need a Dua customer ID of the size 2000 also required we'll also need a user's first name this one can be a bit shorter maybe 100 and required we can also add another one which is the last name also 100 we can add the address one which we have on our form we can do like 100 I think it's not going to go more than that we also need a city remember we have that in our form so it's also 100 and required we also have a postal code which will also not be larger than I think even 10 and it will be required and we have a date of birth make sure to spell these exactly as I'm spelling them everything matters Alpha numerics hyphens whatever you put here will need to refer to it exactly the same within the codebase I'll make this one a bit larger about 100 characters and required to true and we need the SSN social security number let's do about 50 characters and the required great in these fields form a user and now that we have the user we are ready to set up are off and I'm so excited to tell you that server side rendering is now fully supported within aight even though here it says it's unreleased on cloud I have spoken with the aight team and as of the moment you're watching it on this video right now server side rendering is also fully supported on aight Cloud which is perfect for using it with nextjs here they go deep into explaining how the server side rendering authentication flow works even with graphs and so much more but in general server side rendering is more secure and faster and we can skip this guide because I will teach you how to do it within nextjs specifically we'll follow app right's new NEX GS SSR tutorial linked at the bottom of this page it has eight steps and it will teach us how to implement server site o throughout this course I'll follow the app right's guide because I they always want to teach you how to use documentation to your advantage and this time it's no different but of course on top of the documentation since you're watching this video you'll be able to dive deeper into everything and implement it within our banking app with me so with that said let's get started the link to this Appo tutorial will be in the description for the first step you need to have the recent nodejs version as well as a basic knowledge of nextjs and react which if you're watching this video you have already second step we have to create our project which you have already done and step three is we have to initialize the app right SDC so we can do that by creating a function to build Services we need in a file like Source lib server aite and then exporting all the instances so let's do exactly that I will copy this entire file and create a new file within server appjs So within our codebase I'm going to close all of the currently open files and go to lib and create a new file called aight. TS and then paste the code that you copied right here now looking at the tutorial they will kind of explain what's Happening Here we set the current user session if they're logged in done by accessing the session cookie talking about environment variables which we have already done creating the project which is done already and we can go go to the fourth step which is getting the logged in user but before we move on to step four I want to make sure that you fully understand the code that we copied so starting from scratch the first thing to note is this use server directive which we learned about not that long ago this means that all functions exported from these files are server actions we have created some server actions of our own within actions user actions and these are aites user actions then the first thing we can notice is that we haven't yet installed the node aight package so let's do just that by opening up our terminal and running mpm install node Das aite as soon as it gets installed this red squiggly line should be gone and now since we have installed the package we're getting some other warnings letting us know that this could potentially be undefined in this case we no it's not as we have it within our environment variables and we can let typescript know that by adding an exclamation mark at the end of the line we can also repeat that here so now let's explain what we're doing with this create session client function we're creating a new ight client and setting its endpoint in project so that that ight client knows exactly which ight project it should modify in this case it is our JSM Adrian banking project because that's the ID that we pass to it and this function is responsible for creating a session client so that every time that we try to get a session it's going to validated and ensure this is the correct ight session so instead of saying my custom session we can say ight session right here we check if a session exists if it doesn't we return no session otherwise we attach this session to this client and that way every time we want to get access to that session we're going to just use this G method and extract it and similarly we're doing that for the create admin client as well where we set the endpoint project but this time also key as it needs some additional permissions and since we're providing the key here this admin client will have access to all of the functionalities and will be able to do basically anything with our aight project because if you remember we gave our API key full permissions for databases authentication storage and more so we can do anything with this one and we have to keep it secure whereas this one can simply return a session now that that's out of the way we can make this admin client return some additional stuff to us such as get database which is another getter method on it and I know this is not your typical syntax you're used to this is more so a class-based way of writing it where you have gther methods but a get indeed is a valid JavaScript keyword and this is a very unique way to use it so we can get database and then we can also return databases client and of course we have to import this databases from node app right and we have to create a new instance of it by adding the new keyword and we can duplicate it one more time to get not only databases but also users so get user new users coming from node aight and we pass it the client so now we have created two separate server actions allowing us to fetch sessions both for the regular user and for node admin which allows our API to do whatever we want with it now we can focus on the fourth step which is getting the logged in user we're going to build a quick utility function to get the logged in user from aite we can use it within all of our components and routes to quickly check if a user is logged in and access the user details so we can put it either within this new file we have created or since it's a user action we can put it where we already have all the other user actions so let's copy it and let's move away from aite and move to the user actions where we have sign in and sign up and I'm going to also paste the get logged in user of course we have to import create session client and for now we're simply returning that account. getet later on we'll do some additional stuff here now we can call this get logged in user within any of our client or server components pretty cool we'll explore that soon but for now let's move over to the create signup page where we can add the functionality to our grade signup form we don't have to copy this as we have already created a pretty cool form but rather we can create this new action called sign up with email by copying lines 17 to 27 of this file and then putting it within our existing signup specifically within the tri block so we have already laid the foundations for making this happen now of course we have to import create admin client from that slaight we can import the ID coming from node app right 2 by the way I just double click the word and then press control space and that helps me with the Auto Import if it doesn't work for you you can just manually import it like this from node app right now you can notice how we're passing some email password and name into here and we're getting all of that through our user data right in per raps and we have to pass it in a very specific format so you can notice how we have account that create first parameter is the ID then email then password and then name if we have it or a phone number or something like that in this case we have a user data that has a bit more stuff right a lot more stuff so how can we pass only what we need well first of all we can store this new user into a new variable by saying const new user account is equal to await account. create now let's space this out a bit better so we can see what's happening the account create accepts the ID the email the password and an optional name and we can see that if you hover over the account create where it's going to tell you that it needs a user ID email password and name now we have to ask ourselves how can we get access to those well thankfully the email is within the user data. email password is also within the user data. password and for the name we can just concatenate together two strings by saying first name and space last name like this and of course all of this is coming from user data so what you could do is we can destructure those values at the top by destructuring the email the password the first name and last name is equal to user data so this is called a destructuring syntax and now you don't have to say user data every time you can just pass email password first name last name and all of that together when passed to the aites account create results in a new user account great now after that we want to create a session by awaiting account. create email password session by passing the email and the password and finally we get the cookies and then we can import cookies from next headers and you have to rename the app right session to whatever you called it when we initially set it up that's going to be within the aight file and you can go to create admin client no it was create session client and here it is aight session so it has to be the same you pass the session secret path all of this can be the same and finally we want to return parse stringify coming from utils new user and let me explain why we're calling this special utility function that basically runs the json. parse and then json. stringify on the user object well we do that because in nygs you cannot pass large objects such as the entire user object like that through server actions rather we have to stringify it first so that's exactly what we do but not with the new user rather with with a new user account and now we have created this great signup function let's see what do we have to do next the signup is an async function that takes the form data as an argument it uses the create admin client to create an admin ight client and then calls the create email password session on the account object we then set the session Secret in a cookie and redirect the user to the account page great the next step is to create the account page which displays the basic information about the user but I guess this comes after we actually authenticate them so let's do exactly that let's use this signup function within our form so we can navigate over by pressing command P to our OD form and we can actually use the signup server action we have created not that long ago and we're passing data to it but now typescript is complaining a bit because within signup we have these sign up for Rams to which you can go to if you press the ALT key or the command key and some of these are going to be optional so you can hold the option key and select all of these at the end of the lines right here I think all the first ones besides the email and password and we can add a question mark here at the end which will make them optional and no longer should it complain right here as you can see great so that's good even though we know that they actually will be there for the signup form because we have the Zod validation protecting us so that's why we can do that and for now I'm going to comment out the sign in because we're focusing on signup now great so with that in mind the user actions for sign up has been completed we have connected it to our o form and I think we're ready to test it out oh it looks like I didn't check out my local host in a long time and there's an error there it's complaining about the process. EnV at this point about some unexpected character is it possible that when I copied it it contains some hidden unexpected characters well let's check it out it should be within the aight file oh would you look at that there is an invisible character right here I have heard of some programming horror stories and one of them is people putting invisible characters within other people's code and then letting them copy it I think I fell for that trap right now so if you have these invisible characters right here make sure to remove them it's possible that this error gets fixed by the time that you follow along with this tutorial but if it's there for you click the S press the right arrow key it's going to move you to the invisible character and then delete it and then repeat the process for the other ones again press the S move right and delete and I'm going to do it a few more times one two three and I think we are good great going back to our signup form now it works and we can enter my name and last name and address let's do something like interesting Road one two 3 city is going to be let's do New York City and we can do New York yor as a state as well make sure we have two characters postal code has to have around five date of birth can really be anything here we don't have any protection for that and for SSN we can do 1 two 3 4 enter your email and password make sure that it has more than eight characters and let's sign up before I click that from experience I know that it's good to open up inspect element and the console and the network Tab and to clean it up because when you do so much changes like we have done right now it's good to see what the computer will say once you click a button so let's give it a shot I'm going to click sign up it's loading which is a good sign and we get redirected to sign up but now it says Link account which is perfect because if you remember within our o form when we worked on different conditions it's only going to say Link account if we actually have access to the user object and back on aight dashboard which by the way looks great in dark mode but this light scroll bar jumps out to me a bit I should definitely let the aright team know to make it dark and then maybe by the time you're watching this video it will be dark so if you reach this point and if it's dark let me know that in the comments but with that said let's go back to oth and now you should be able to see a new user got added to our database so let's click on it and not only can we see its name and email and additional information you can also go to sessions and see that we have an active session on a Mac OS device in Croatia and even see the IP address so now going back to create account page we don't necessarily have to create the entire account page but we can try to access some of the information from that user and I think that's what they're doing here yeah we're more or less done with this tutorial so let's just see if we can extract some information from that user so now let's see if we're getting the user at the start it is null but then on the submit Handler we set it right here so let's copy this right here const user is equal to a wait get logged in user and within our code we can paste it right here at the top we can rename it to something like logged in user is equal to await get logged in user and we can import it from lib actions now this is a client side function so it will be a bit harder to call it from within here as we cannot use the top level of weight but if we go to the sign up page and try to call it here of course by importing the lib and making the function a sync we can try to conso log the logged in user and now we can open up our terminal right here it's not going to be in the browser as we're working with the server side and as you can see we get null right here so it looks like it's not returning the user so if we go into the get logged in user and open up the function it looks like this return await account. getet is returning a null instead of an actual user I think the reason we're getting a null is the same reason why we used this parse stringify when we send the new user account because in nextjs we cannot send objects from server actions to the front end like this so instead we're going to store this in a new variable by saying const user is equal to a weight account. getet and then we can return a parse stringify and then we can pass that user right in now if we save this we're still calling the same function conso loging get and if we go back to Local Host and reload we still get null and I think I know why that is I have provided you with some names for our environment variables as you can see here next public ight project database ID and so on but when we were following aight documentation they might have named those things differently so if we go to aight let's see next public aright endpoint and next public aright project aright endpoint aright project those two seem good what about next aright key that's what I called aright secret so instead let's follow their docs and let's rename our EnV to next aright key and we can also do it in the EnV example next aight key instead of the app right secret now that we have done that hopefully we should be able to see our logged in user so I'm going to reload our signup page and then let's simply create a new mock user I'll be a bit faster this time and just put some random values there we go email I'm going to do Adrian gmail.com and my password and sign up looks good we're redirected to the link account part and this time we get the full user info that is great awesome so now we know that we actually have a logged in user we don't have to use it here within the signup but I just wanted to show you that to ensure that it works and hey it actually does we have successfully created the signup function the get logged in user and within our OD form we're successfully calling the sign up and setting the new user to the state now we can focus on sign in so let's navigate over to user. actions. DS and let's expand sign in within here we'll have to do a similar thing like we're doing right here like trying to extract the account from create admin client but then instead of creating a new account we'll create an email and password session on the existing account so to do that we can go right here we can copy this const account is equal to create admin client and put it within the try once we get that we can say con response is equal to await account do create email password session and we need to pass the email and the password and if I'm not mistaken these are the only two things that we are indeed passing into this function we're passing them as an object email is equal to data. email and password is data. password so here we can destructure that and get the email and the password as the only parameter and we can make that of a type sign in props and after we get the response we can simply return remember parse stringify and we can return that response to the client side or to whatever function is calling this specifically that will be our form so going back right here we have the type sign in we have the response and we're pushing right here and if we do get back a response we're pushing the homepage so what do you say that we give it a try we can now navigate over to sign in and we can use the email and password that we have created our account with if the sign in is successful we should be redirected to the dashboard great and now that we're here what do you say that we make this name dynamic as well as this name here and the email currently all of that is static data we have hardcoded at the start but now we can fetch it from the logged in user session so going back to application we can now navigate over to our home page so that's the root page and instead of this logged in being just hardcoded information we can now SA say con logged in is equal to we can say get logged in user coming from lib actions and now it will just complain as it doesn't have the first name so if you see the get logged in user it will return a user as you can see here but now it won't be first name rather it will be just name and we have to make this a wait as it's actually a promise so we have to make the function a sync or rather the whole page as soon as we do that we have to fix it in another place too and that is when we pass the user to the right sidebar so we can navigate over to the right side bar and instead of user. first name zero say just user.name and here instead of rendering those two we can just render user.name and we'll have to dive into the right side bar props and modify this user type and then alongside first name and last name we can also just add name of a type string so now if we go back you can see it's no longer complaining it looks good and now it says welcome ASD as I was just typing some random stuff but you can see that indeed it is pulling the data so to make this make a bit more sense let's implement the log out functionality so we can log out and then log in with a better account to do that we can go to user actions and we can create a new user action export const logout account is equal to an async function that has a try and catch Block in the cat we can simply return null and in the try we can get the account from the session by saying const and then the structured the account is equal to await create session client and then we can call the cookies. delete and we can delete the ight session make sure to call this exactly as you called it before after that we're going to call the await account. delete session and we're going to pass in current now we can add a button that will log us out that will be on the left sidebar which is called just sidebar scroll to the bottom and here I told you we'll Implement a footer so now is the time that we create a new footer component to which we will pass the user is equal to user if we save it it will break so let's go to components and create a new footer. TSX component with rafc and we can then import the footer from slf footer now on the sidebar it is there at the bottom but it's white text so it's hard to see it so just to show you what we're going for we want to show even more user information such as the first and last name some kind of a profile photo email and then the button to log us out so let's create it by turning this into an HTML 5 semantic footer tag with a class name equal to footer and we can recall this footer component also within our mobile nav so let's quickly navigate to Mobile nav and at the bottom we can call this same footer component coming from slf footer don't forget we also have to pass the user which is equal to user great now within this footer we can have a div and that div will have a class name equal to footer name and within it we can create a P tag that will render the first character of the users first name so let's get user info from the props by destructuring the user it's of a type footer props and we can say user DOT first name and then zero that'll get a in my case we can also style this btag further by giving it a class name of text- excl font D bold and text- g-700 and it's it looks like nothing is there oh I think that's because we're using the footer name which is a class for the desktop sidebar so we need to pass an additional prop right here which is type and the type can be either desktop or mobile so maybe we can pass mobile here and then on the original sidebar by default it can be desktop so if we go here we can accept a type which default will be set to desktop and in footer props we can also add a type and this type will be either mobile or desktop and it will also be optional if we don't pass it great so now we can check right here if type is triple equal to mobile then we will give it a class name of footer underscore name- mobile else we'll give it a class name of footer uncore name and we can close it right here so now if we save it there we go it appears right here great let's also go below this div and create another div with a class name equal to and we'll copy this entire class name we have here paste it here and instead of footer name mobile it's going to be footer email mobile and it will be footer email here now within it we can render an H1 this H1 will render the user first name and last name so we can say something like user. first name or I think we can just do user.name everything should be contained there let's give it some classes like a class name is equal to text D14 truncate font dormal and text- gr- 600 now the reason why nothing is showing right now is because our user is still a fake mock user let me show you why if we go to mobile nav you'll notice that this user we're getting from the top is actually a user which we're passing to the mobile nav so if we see where we're calling our mobile nav we're passing the user logged in but this logged in is for now fake so we have learned how we can do it properly we can say await get logged in user and we have to make this function a sync so export default async function now we're getting the Rel logged in user and then in the footer it doesn't have the first name as the user only has a name there we go we go back and now we can see Asda a ASD okay that's good so now below this H1 we can render a P tag and that P will have a class name equal to text -14 truncate font dormal and text- gr- 600 and here we can render the user. email there we go we have to somehow differentiate the email from the name so let's make this a bit of a darker color and let's also give a font Das semibold there we go that's better and finally we can go below this div and create one last div with a class name equal to footer unor image and we can render an image which we have to import from next image give it a source of icons SL log out. SVG and ALT is JSM and that is the logout icon there we go now to this div we can pass an onclick listener and we can call the handle log out function which we can create right here on top by saying const handle log out is equal to it's an async function and here we can call our server action by saying await log out account coming from user actions to know whether we have been logged out for real we can store that in a variable logged out and then if the user has been logged out so if logged out then we can use the router and push to the sign in so we have to initialize the router by saying const router is equal to use router coming from next navigation and then we can say router. push and push to sign in so we can sign in again with another user also I noticed here I used font normal it was supposed to be semi bold great now let's also check it out on desktop there we go that looks good we know who currently logged in whoever this guy is and on the card I noticed undefined undefined and here as well so let's quickly fix that if I navigate over to the card component and search for username you can see that the username is coming as undefined so let's see how we're passing it into the bank card we're passing it as a combination of the first name and last name and here I think we can just get the user.name I think it will contain everything we need and also here we can pass it just user.name so now back in the bank card we can simply use the username and here username as well and now we can see it has these random letters and I believe now we have made all of this static data Dynamic so let's give log out a try I'm going to press here and we get canot read properties of name reading null at footer okay so let me quickly go to the footer and here just in case we don't have it I'm going to add a question mark here which should protect us from that error in any case there we go and looks like I missed the spot in the right sidebar but now that I think about it we should never be on homepage it looks like we got redirected back to Local Host 3000 and now to sign in even though we're not signed in so that's the reason why these errors are happening this is an edge case anyway but either way a user should never be able to see this kind of an error so instead of fixing all of these individually it's better to go to the layout and navigate the user to the sign in if a user isn't logged in so going all the way here to the page root and then layout of all of these Pages we're checking whether the user is logged in so here we can add an if statement and say if no logged in so if it's faly in that case we can initialize the router by saying cons router is equal to use router coming from next navigation and we can say router push to the forward slash oh and we get an interesting error saying that we're using the used router but the component is not a client component and yeah silly me it's not a client component it is server and we want it to remain that way so let me show you a quick trick instead of using the used router instead we can use the redirect coming from next navigation and then we can simply say redirect we don't have to use the push we just redirect to forward slash sign Das in and if we do this we are there so now we're successfully logged out which is great and just to be 100% safe I want to go to the app right o part and I want to delete all existing users so we can create proper ones with real names this time so I'm going to scroll down and delete each one of these three one two and three and while we're here I just got reminded that for this entire time we've been seeing the mobile version of the authentication but we haven't seen the desktop version too many times and now that I see it it looks a bit empty so what do you say that we make it look exactly like it does on the design to do that we just have to add this image on the right side so let's just quickly jump over to layout of the authentication and alongside returning just the children we can first style this main by giving it a class name of flex m-- screen w- full justify between and font denter and then below the children we can render a div with a class name of O asset and render another div within which will render this image so let's import image from next image let's give it a source equal to SL ions SLO Das image.svg give it an ALT tag of O image a width of 500 and a height of 500 now going back it looks something like this and I think we're a bit too zoomed out now so let me zoom in to 100% And this actually looks great we have the image on the right side we have sign in here and we can also switch between sign in and sign up this is great so now let's finally create a real account I'm going to try to enter some information Adrian JS Mastery let's enter some kind of a cool address address 1 2 3 New York City and Y 1 2 3 4 5 and we can do this and enter my email there we go and let's sign up it's loading and we are redirected to link our account which is exactly what we want to happen we don't want to immediately get redirected to the home because then we wouldn't be able to see anything thing as we haven't yet passed the onboarding or simply put the process to link our bank account but if you want to check out the homepage we can do that now by modifying our URL and going to forward slash because now we are actually logged in and we're getting all of this information from a real upright o session that is great soon enough you'll connect your app with played which is similar to stripe and in this case we'll use a Sandbox account so you'll be able to connect it no matter where in the world you are and it will allow us to check our bank accounts check out our transaction history and even transfer funds between our different Horizon accounts exciting stuff ahead but just before we do that I want to show you something that's very important especially for the application like the one you're building right now when you have a banking account you want want to make sure that your application's up time is that famous 99.9% online because we're processing transactions you want to make sure that absolutely everything goes the right way we're talking about people's money here and for that reason first of all has to work flawlessly but second of all there's a lot of privacy involved so if something does go wrong how can you debug the app for the user if there's all of this sensitive data we're talking about especially during the registration process when they have to enter their date of birth state postal code and even social security number in this case well let me teach you as I told you at the start you'll power this application up with Enterprise grade application monitoring software where if code breaks you'll fix it faster specifically for a banking app we leverage session replay which will allow you to get to the root cause of an issue by watching replays of real users and here's the key thing you won't be able to see their data or social security number but you will be able to see exactly what they're doing and which errors they're getting so let's log out and let me teach you how to add Sentry to your app to get started you can click the cental link down in the description make sure to to continue only through that link to be able to follow along and see exactly what I'm seeing so once you do that you can go to get started and you can create your account or sign in with one of the options once you register you should be able to see something like this and if you have created your account before you can just add forward slash onboarding to your URL and it should renate you here now let's click Start under install Sentry let's choose nextjs and configure SDK it'll give us a special command which we can use to spin up centry so let's copy it and back within our application we can paste it press enter and press y to install the Sentry wizard it's going to ask us a couple of questions so let's say yes first of all do you want to self-host or use Sentry SAS we're going to use Sentry IO you already have a Sentry account well that's a yes it will just log you in through your browser you can select your Sentry project and you can select this JavaScript nextjs project which was created for you by senty when you ran this wizard it's going to install the necessary mpm packages it's going to ask us if we want to Route Sentry requests in the browser through our nextjs server to avoid add blockers for this one we can just select the default no for now then we can let Sentry create an example page we will be using cicd tools like GitHub or in this case verell and finally yes continue great well that has been simple we have successfully set up Sentry for our project now let me show you the files that Sentry has automatically generated for you starting with Sentry do server. config this initializes Sentry on the server it has the traces sample rate allowing you to track how many users visit your website and you can even modify some additional Flags similarly we have that for the edge Network and also for the client side all of these files have been generated for you as well as the next config has been modified to include your organization and project within Sentry so if you want to fully understand what is happening within these files you can go here command or option click the docs and then if you're feeling bold you can ask a bot and typically these AI Bots are not that intelligent let me put it that way but I've tested Sentry bot a bit and it answers all the questions incredibly well so for example if I copy traces sample rate one and ask it what does traces sample rate one do and paste it let's see how good it is there we go it says that the traces sample rate one configuration sets the percentage chance a given transaction will be sent to Sentry 100% this means that all transactions created in the app will be sent to Sentry for monitoring and tracking one represents 100% probability okay this is a great response and another cool thing Sentry has prepared for us is right here at the top under app Sentry example page and then here we have a page that says get started by sending us a sample error so they invite you to break your application on purpose how bold of them so this page is under Sentry example page and since you're a nextjs expert you know how to reach this endpoint you just have to go to Local Host 3000 and go to Sentry EXA example page press enter and here is that sneaky button throw an error there we go the error has been thrown Sentry example fronted error you can think of this as a typical error message that your user would get while they carelessly use your application you know that feeling when you develop it for hours you test it and everything works but then a user comes and breaks it in a second well this is for cases just just like that so now that we threw that error let's go back to the onboarding and at the bottom you should be able to see error received take me to my error and would you look at that unhandled error Century example API route we can see when it has happened we can see where in the code that originated and this little onboarding also tells us how bad it is find problematic releases and more stuff but what I want to know is exact actly which user broke that and we can see the user node version Mac OS version and even the browser and more information on it and now let's see what other information can we get out of this report first of all I want to go to replace and right here we have a single replay coming from a single error so let's click it and check this out we can start playing this video and we can see exactly what the user was doing on the screen when the error happened we can see their cursor how they were moving it and what they were doing here they clicked it and they broke it but as you can see there's dots instead of actual characters so everything is completely secure which matters a lot for banking applications also you can see exactly which element they clicked on as well as the entire console they were seeing at that time as well as all the networks errors and more I mean how cool is that imagine not having to speak with your customers and try to debug the errors with them but rather being alerted immediately their app breaks and then being able to fix it immediately after and for the final time let's go through the signup process because I want to show you something cool I'm going to use a John Doe as an example I'm going to do a very cool address in a city let's do Los Angeles and and let's do la with a postcode of 1 2 3 4 5 date of birth can be some random numbers Social Security numbers can also be random email is going to be very secure email gmail.com and we can enter some hard password and now I want to first of all remember this so I can later on sign in and then I want to sign up if I do that I'll be redirected Ed to link account and I can quickly go over to my homepage welcome John Doe we can see the total current balance we can see the very secure email and even some card details right here and of course we can also move through different pages and even though there's no important data right now while our user was registering a lot of important data was shared so now let's go back over to sentury and see if we already have a replay it doesn't show up directly on the replay page because I think only the ones that have dead clicks or rage clicks or errors show up here but rather let's explore what else we have or in Sentry and we can find it along the way under queries there's not a lot of data now under requests we can see all the requests our users have made on Local Host Sentry example page the average duration time spent and more under web vitals it's slowly starting to load all of the most important web vitals right now they're not too good so we can fix that later on but if we go to discover I think we can see almost everything about our application we can see all the events that happened in the latest interval we can merge them by total daily and even change the count by unique users so we can see exactly how many unique users have visited our website right now it is one just me and here we can then dive deeper into each one of these transactions so here we have my Banks we have the layout let's open up the sign up page right here or the sign up transaction and here we can see what our user has been doing on that page ever since they transitioned from the airor page to sign in and then sign up and here they have been inputting all of their data and if we make it a bit larger you should be able to see exactly what is happening there we go you can see how a user is slowly typing these things in but we on the monitoring side cannot see anything the only thing we get are the actual errors that happens and user navigations that allow us to debug the page wonderful this is the power of senty of course there's so much more stuff like the user feedbacks where you can create a form through which a user can give you feedback we also have metrics where you can track everything that is important for your application such as the average transaction duration and you can also have custom dashboards allowing you to track the most important metrics of your site like web vitals as well as how many errors you have by browser in percentage or by a specific user and in the general tab you can even track Errors By country Errors By browser ER issues assigned to you and your team you can track a lot of stuff and you can of course fully customize that dashboard and track whatever you want to track errors crash rates even miserable users who have the worst experience out there you can track it all and fix it all that's how Sentry works we'll revisit Sentry later on once we deploy our application so we can continue monitoring it for errors but for now let's go back to our application and let's delete this Sentry example page and the global error as we don't need them anymore now we can focus on our next task and that is finally integration with our banking system of choice plate before we do that let's make sure to push everything we have committed so far and let's give it a proper name here we have fully initialized aite Sentry and we have also completed the O layout so we can say Implement o aright and Sentry and I'm going to do a commit and sync the changes great with that said let's start working on what you came to this video for in the first place implementing the banking functionality to develop banking functionalities within our application we'll use play now you may wonder what the heck is plate well plate is like a middleman between apps and Banks it helps us connect the two securely and here's why you might want to use it as a developer it gives us a simple way to connect our apps to thousands of different banks it makes sure that data that we send between the app and the bank is secured so we don't have to handle the sensitive stuff and it follows all the banks regulations that and rules so we don't have to in short while it might seem like a good idea to connect directly to Banks play makes everything easier and safer for all of us it lets us focus on developing our app without having to stress about the details of Bank connections and LW so click the link down in the description to follow along and then click this get started button on top right it will lead you to a quick on boarding where you can say that you're a developer enter your email address enter your full name company name and if you don't have a company feel free to put JSM JS Mastery or something like that choose your country and password and create your account once you do you'll be redirected to the play dashboard here we can test plate products and specifically we'll be working on the integration of connecting multiple bank accounts to our application and of course we'll start in the sandbox environment so let's close this go to your email and verify it and for now we don't even have to request the production access as we'll be working on the development environment and directly in the dashboard you can click quick start I would highly recommend that you watch this 3 minute long video as it will explain how we'll be using played throughout our application it is developer focused and it basically explains how we'll create a Sandbox environment and then use client IDs and secrets to connect pled to our server site application and then through pled connect different bank accounts so it's a good watch with that said we can go back and back in the dashboard we can expand our developers tab on the left side and go under Keys here you can see our client ID you can copy it back in our Visual Studio code we can go to our environment variables and we can add under played client ID you can repeat the procedure with secrets so copy it and paste it here and same thing for sandbox so we have development and sandbox in this case we just want to use the sandbox so you don't need a secret for development at all under plate EnV we can say sandbox as that's the one we're using and under plate products we can say Au comma transactions comma identity and under played country codes we can say us and CA the United States and Canada again this is just a test environment but it should work no matter where in the world you are now that we have the keys we can start with the integration and now that we have the keys we can start with the integration back in our terminal we can run mpm install react DPL daslink this will allow us to link our bank accounts great the package got installed and we can dive right into the code we can start with the configuration by going over to lib and creating a new file called plate dots within here we'll need to set up a new play configuration and alongside installing react blade link we also need to install the general plade package by running mpm install plate now we can import some things from plate such as configuration play API and play environments and that's coming from plate once we have that we can initialize our configuration and make it equal to a new instance of a configuration class which we call and we can pass some params such as the base path equal to played environments do sandbox and base options that's an object where we have the headers and here we can use our environment variables by setting up our played client ID equal to process. env. played under _ centore ID as well as a pl- secret which will be equal to process. env. plore secret and you have previously added all of these variables to your environment variables finally we can export const played client and make it equal to new played API inside of which we pass our configuration and this is great because we can see that a lot of these softwares have different things in common such as aight you do the same thing you create a client and expose it to app and then you can use that app client to do all sorts of things in a similar fashion you create a plate configuration and a plate client which then you can call within your server actions that's it for the config pretty simple but now let's put it to use going back to our o form if we scroll a bit down you'll notice that we left some space for the played link and that time came so let's create a new component in the components folder and let's call it played link. TSX run RFC and let's import it right here within the odd form played link coming from slpl link now before we go into that link let's pass it some props I'm going to pass it a user which is equal to the user which we already have access to and I'm going to pass it a variant as there will be two different situations where we'll use this plate link so let's pass a variant of primary for now now let's command click into that plate link and let's accept all of those props we can do that by D structuring the user as well as the variant of a type played link props and right within here we can create a button that will allow us to connect a bank so let's return just an empty react fragment and within it check out our variant if the variant is triple equal to Primary in that case we can return a button this is a shaten UI button that will say connect Bank else as the second part of the turnery we can check if a variant is triple equal to ghost this will be a new one which we'll use soon in that case we can return another button which will also say connect back but we'll modify the Styles a bit and if it's not either one of these variants then we're going to return a third thing which will also be a button but with a bit of a different styling it will also say you can guess it connect bank now let's figure out where this button is on the screen first of all we used it in the odd form so it will be in/sign up and if we go back to the odd form right now in this page we're not checking for the active user session so it won't know that we are actually logged in so for that reason we can simply comment out this check so I'm going to comment out the user as well as these lines right here and of course the ending part of the tary operator which will be all the way there that way it will show right on top and now we can see it for the time while we're actually building it out great going back to here we can continue adding some Styles such as we can give this button a class name equal to played link Das primary and let's spell it properly so it can be played link and immediately you can see that now we have a regular primary button allowing us to connect the bank of course what would this button be without a function that does something when you click it in this case we'll refer to plates documentation specifically the link web SDK a reference for integrating with the link JavaScript SDK and react SDK we have already gone through the installation process so we can scroll down to the usage I won't be copying anything here rather I will teach you how to do it from scratch so first things first we have to create a config object and let me just increase the width just a bit here and let me also just increase the width of our editor just a bit there we go so now let's create a config object cost config of a type played link options coming from react played link this will help us with our typescript is equal to an object where we can define a token as well as on success handlers you can see that here and now it's up to us to Define that on success function we can Define it right here above by saying const on success is equal to and usually this is a type of function that you would wrap in a use callback as we don't want to recall it every time it gets called rather it's just a callback we're passing that happens on success so you can import used callback from react and the way that that works is you just wrap it is that you call it as a hook and then within it you declare a new async function so we can say async open it up and it can be unnamed like this and as the second parameter of the used callback you provide when it should get recalled and that is whenever the user changes the one we're passing through props okay so now we have an empty on success but what about a token well let's create a new use State field which will help us to get access to that token use State snippet let's call it token and set token at the start equal to an empty string and let's not forget get to import use state from react then we can also form a use effect so we can fetch that token on time a use effect works in a way that you create a callback function and provide a dependency array on when you want that function to be recalled and of course don't forget to import use effect from react within here we cannot simply say something like a wait fetch token even though you might think you can make this function a sync this is illegal in react you can never make this first function within use effect a sync instead what you need to do is create an internal function const get link token is equal to an async function and then you can use a weight within here and you can immediately call the get link token below this is how you do acing stuff within the use effect now within here we'll want to somehow fetch that data by saying cons data is equal to a weight create link token to which we want to pass the user so we want to connect our existing user which is logged in to a played user through a token for now this function doesn't exist create link token so we can comment it out and we'll soon create it as a server action finally once we get back to data we can set the token to be equal to data question mark. link token for now we can comment that out as well next let's figure out what happens on success well here you're going to get access to one parameter public undor token and it will be of a type string so right here on success we want to exchange that public token which will allow us to link a bank account so we can say await exchange public token call it as a function and pass one parameter that is an object of public token which we need to call public uncore token as that's how we're getting it from the props or from progams and then we can pass the user as well and of course this is a second server action we'll need to create so let's comment it out for now and after we exchange the public token we want to push to the homepage because that means that we have successfully linked our bank account so let's just quickly get access to the router by saying cons router is equal to use router coming from next navigation and then right here we can say router. push to slash great so now we have laid out the foundation for on success and the token which we need for our configuration and right now it's complaining a bit that this on success is not of the right type so what we have to do is assign the type of played link on success by saying use call back and then immediately after Define a type of play link on success which we can import from react play link and it looks like I made a typo here this was supposed to be just string there we go so now we have on success we have the use effect and we have created a configuration object needed for the next step which is this right here to be able to use a use played link hook so right here let's say const and let's D structure the open as well as ready state by saying equal to use played link to which we passed the config we just created and don't forget to import use plade Link from react blade link link now that we have that we can finally do what I told you we would do and that is make this button functional by saying on click is equal to open and as tabt is complaining in this case we need to make it a callback function which would look something like this finally we can give it a disabled state if not ready in that case it has to be disabled and as you can see in its current state it is indeed disabled so so now we have to do our best work to create a link token so let's navigate over to our lib actions user actions and let's create a new server action export const create link token which is equal to an async function that accepts the user of a type user as the first and only parameter and we can open up a try and catch Block in the catch we can simply console.log an error and in the try we need to create our link token but first we need to define the token parameters by saying const token params is equal to an object here we need to follow a specific structure to let played know what we want to do with their product specifically we can say user is an object where the client user ID is equal to user. dollar sign ID alongside that we have to provide it a client name and this will be equal to user.name we can also select which products we want to use and this will be an array with the string of O as products like this make sure to import it from played this is just for typescript we can also choose a language in this case I will make it en for English and also country codes in this case it can be an array of us as country code coming from played and then array like this so now we have the necessary token prams to generate a new link token so let's say const response is equal to await played client. link token create and we need to pass the token for Rams but the question is where is this played link coming from well we have created it before it is coming from the played file export con play client so let's import it at the top by saying import played client coming from atli SL played great and now that we are generating this response the response should contain a token so we can just return a parse stringify of an object saying link token is equal to response. dat. linkcore token and there we go that's how you create a link token using plate so going back to our OD form or rather to our played link component we can uncommon this part where we get and set a new token make sure to import create link token from lib actions and add a user to this dependency array great and now for the second missing piece of the puzzle The Exchange public token server action so let's go back to user actions and let's created The Exchange public token function is a one that exchanges our existing access token for a token that allows us to do stuff and by stuff I mean banking stuff and there's a lot of banking stuff here first of all connecting our bank account making payment transfers between accounts and even connecting a payment processor so we can transfer funds in the first place there's a lot of stuff so let's dissect it together what we're about to do in this function starts right here in step two of our logic map which of course connects our bank account with our thirdparty applications in this case our banking app Horizon so what happens first is we generate a played link and to do that a token is required to initialize a played link client component so here's the process and here's exactly what we'll do in the next function first we create a link token then we pass the generated link token to play link then we trigger a flow of connecting bank account to application through played link on success played link will provide a temporary public token and then we want to exchange that public token with a permanent access token then we exchange the access token to get the bank information and then we connect with processor which we'll talk a bit more later on in this case dalla is the payment processor of choice but the most important thing here is that this is a handshake first we pass something to play link then it gives us back the temporary public token and then we exchange that public token for an access token okay that way play knows for sure that we are a legit actor trying to get legitimate information in the read me down below you can find the complete exchange public token function so take it copy it and paste it here but for now I will explain it step by step first we have to create a typical server action called exchange public token that accepts a public token and a user as two different parameters then we want to open up a new try and catch Block in the catch we can simply kol log an error simple enough right in the try we need to exchange our public token for the access token and the item id which is contained within the response here and we do that by awaiting played client do item public token exchange where we provide our public token in exchange for the access token so let's extract the access token and the item ID from the respon FS we have just gotten now that we have those we can get the account information from played using the access token that's going to look something like this and since we're working just on the code now I want to expand my visual studio code after we get the account response we can get the account data from it and once we have the access token and account data we can create a processor token for dalla and dalla a bit of a weird name but it's a payment processor we'll be using for processing our money through played on our platform so we can do that by creating a processor token using the access token and the account ID by first of all generating a request object for that token and we can import these stab script types from played once we have the request token we can generate a processor token that will look like this cons processor token response is equal to await plate client. processor token create then we get access to the processor token and now we have to fund our account somehow so we can create a funding source specifically a funding source URL for a specific account using the dwala customer ID the processor token and the bank name think of this as connecting the Payment Processing functionality to our specific bank account so that it can send and receive funds this add funding source is a special server action coming from dalla and thankfully they have a very good documentation page where I found all of those functions more than that soon but after we get the funding source URL we want to make sure that it actually exists so we can create a new if statement right here and finally if a funding source exists we want to create a bank account and that's going to look something like this we create a bank account using the user ID Item ID account ID access token funding source URL and the sharable ID so the users can transfer money between different accounts this encrypt ID is coming from utils and this create bank account is a server action which we will create together very soon finally once we create a new bank account we want to revalidate the path to reflect the changes and this is coming from the next cache which will allow us to basically see the new account we created on the homepage and then we just want to return a success message after all of this hard work by saying Return part stringify public token exchange complete great so this was a tough one and we covered a lot of ground and it might take some time for all of this to settle we will revisit this later on but for now you just have to know that we exchanged our public token for the access token allowing us to create a bank account we got that account data and then we also connected a payment processor called dalla and allowed ourselves to transfer funds between different accounts now with that said how can we add a funding source using this special payment processor well let's create a new special file under actions called Dua actions dots and the code for this file will be attached to the read me of this project so copy it and paste it and I want to quickly let you know that once you add this piece of code we'll see an error in the browser for a very long period of time while we're fixing other stuff but don't worry about that error we'll get back to it later on you haven't done anything wrong it's just how it is we'll get back to it later and you might think oh is Adrian again giving me code to copy and paste but sometimes it really is like that because we're using open-source additional soft where the developers that created it thankfully provided us some code to allow us to use their software in a simpler way so as you can see as I am giving you code to copy they have also given it to us in this integration examples VOA GitHub page where we get the environment we create the client and then also all the other functions that we need to make it work and the only thing that I had to add on top of that code was a function to initiate a transfer which I found under duala Docs you basically have to form a request body and then do a post request Ona where you pass that request body indicating which account you want to fund and you can notice here that the source of a transfer this href is actually a URL funding source which we're creating for each one of the users within our platform this will make the functionality of transferring the funds between accounts in our platform work so with that in mind youit now have access to these dalla actions and we just have to make sure to install D- V2 in our terminal by running mpm install w- V2 after you do that it should go from red to green and we can import ad funding source from dalla and I want to take a second here to explain what dalla is on our logical map well first of all we have the main bank application and of course played is used to securely connect bank accounts to other applications and enable realtime transaction data and balance updates so it's simply about sharing the information of data which we have here whereas dalla right here is used to transfer funds okay dalla is a payment processor so here first of all we pass sender funding source URL we pass receiver funding source URL and then the amount and this is what happens if we actually want to make a real bank transfer from two accounts played shares the data between those transactions but dalla actually makes them happen the only other red thing right here is this create bank account and that is a function that you will create so let's create it right here above this exchange public token export const create Bank account which will be an async function and it will accept some props we can expand it open up a try and catch block and we can implement it first things first we have to accept all of the props that we are passing right here below so I'm going to hold the Windows key or that's option on Mac OS and you can double click all of these parameters and then copy them moving back up to create bank account you you can just paste them here you'll also need to add commas at the end of each one and you can make them of a type create bank account props now we can use them to create a bank account and when I say create bank account here I don't mean anything regarding to banking transfers vaa or anything like we have done so far here we're creating it strictly with an ight so we create a bank account as a document within our database so let's do that by saying const we destructure the database which is equal to await create admin client this is the aight client allowing us to create new documents we can say const bank account is equal to await database. create document and this is a method that you call on the database model and it allows you to create a new document and add it to a specific collection so we need a couple of things right here as you can notice first we need the database ID then the collection ID then document ID then the data itself and then optional permissions so let's call This And expand it as the first parameter we're going to pass the database ID and this is coming from environment variables so instead of simply saying process. EnV every time at the top of this file we can say const and then these structure specific values such as aite undor database unor ID and that is coming from process. EnV so this way we simply destructured it and as we know that this database ID is regarding app right we can even rename it to just database ID so to shorten it a bit and we can repeat this process for aite user uncore collection uncore ID that's going to be just user uncore collection ID and we can repeat this process for Bank collection ID as well great so now we can scroll down and we can pass the database ID as the first parameter so in which database we're creating this document in then we have to specify inside of which collection we're creating it in and that's going to be bankor collection ID then we have to give it an ID which will be id. unique this is coming from aite and then an object with all of these variables that we're passing to it so we can basically copy everything we're getting from props or params in this case also typescript doesn't know whether the database ID exists or not as it can potentially be undefined so we can end it with an exclamation mark to tell it hey we know that for sure there's going to be a bank collection ID of course if we spell it properly as right now it looks like it cannot find it so that's going to be Bank collection ID there we go that's good and once we get the bank account back we can simply return it to the front end by saying return parse stringify and we return a bank account now couple of things that are important here for this to work we first have to move our user from just being a session within our browser storage and session within aite to being an actual user within our aight database that's one of the things we have to do and also we have to create a schema of how a bank account will look like within our database and if you remember we have already done that for the user so let's do it one more time for the bank account to do that we have to go back within our app right dashboard and go to databases and go to our bank database and here we have Banks collection and now we have to go under attributes and give it attributes so that our aight database knows how a single bank account document will look like so let's give it a couple of attributes the first one being a string that will be an account ID we can do 2,000 characters required and create we'll also need another bank ID with a size of 2,000 and we can make it required we'll also have to store an access token which will also be of 2,000 and required next we'll need a funding source URL which will also be of 2,000 and the required let's not forget about the sharable ID which is the encrypted version of the account ID making it safe for public sharing so we can call it sharable ID make sure to spell it properly it's sharable ID whatever you call it here you have to also call it within your code it's going to be 2,000 and required and finally we'll need a user ID and this is a reference to our user account so instead in of making it a string let's make it a relationship it'll be a one-way relationship to users specifically many to one that means that Banks can only contain one user but a user can belong to many banks now before we create it we have to change the attribute key to be equal to user ID as this is how we will match the banks with users and on deletion we can set null and click create there we go now we know EX exactly how our bank documents will look like of course now we'll have to actually clear all of our users and we'll need to do that anyway as now we will actually add dalla and plate IDs to each user and we'll do that directly on the signup so now is the time that we dive into the signup and make some modifications as now we're not only just creating a new user and storing it in the cookies we want to actually store it in the database and in Infuse it with play integration now there's one thing that I want to teach you here and it's a very valuable General programming lesson and that is about making your functions Atomic what does it mean for a function to be Atomic an atomic transaction is one that either works or it doesn't there's nothing in between so we want to ensure that if it goes through it needs to go through until the end and if it doesn't it needs to fail we cannot create a user account in the session and then not add the user to the database or we cannot add the user to the database and then not connect to Plate this account creation needs to work flawlessly on all three steps so for that reason right here above the try I'm going to add a new variable called let new user account and at the start I will leave it empty then right here I will reinitialize this new user account to this new account that we create and then immediately after I want to add an if statement saying if no new user account in that case we're going to throw a new error saying error creating user so it will exit out of the function now if we have succeeded with creating a user account that means that we have reached line 48 in my case we we want to create a Dua customer URL that is our payment processor if you remember so we can say const Dua customer URL is equal to await create dalla customer and that is coming from our dalla actions and to it we need to spread all of the user data and also pass the type of personal now we want to check if we have received the dalla customer URL so we can do another check and say if no dalla customer URL in that case we're going to throw another error throw new error which will say error creating dalla customer now that we have the dalla customer URL we have to extract the dalla customer ID by saying const dalla customer ID is equal to extract customer ID from URL you have to import that from actions and then you have to pass the dalla customer URL and now that we have this dalla customer ID we have everything we need to create a new document in the database so let's go to the triy function here and let's extract account as well as database from create admin client and then right here below dalla customer ID we can say const new user is equal to await database. create document and as we have learned we first have to pass the database ID database unor ID exclamation mark then the collection ID in which we want to add it user collection ID then the ID of the new document for that one we'll use the ID unique to create a new one and then an object containing all of the information we need in this case we'll spread the entire user data we'll add the user ID of new account user or I think it's new user account do dollar sign ID and we'll also add a Dua customer ID as well as a dwala customer URL and all of this information will now forever be tied with our database user after we create it we also created session store it to cookies as before and finally we can return par stringify but not the new user account because this is just the accounts stored in the session rather we want to pass over this new user coming directly from the database great now very quickly let's fix this tabs script error as it has every right to complain about us it's saying that argument of type first name optional which means that it can be either string or undefined is not good for first name should be string because to create a Dua customer having that first name is required so once again typescript is saving our ass here so to fix that we can go back to Au form and the only reason why typescript WR now thinks that first name is not there is because to sign up we're passing the data and this data has first name optional and last name optional instead of that we will form a new user data object so const user data is equal to and within it we will just create all of the properties first name is data. first name and we can add an exclamation mark at the end letting typescript know that we know that we'll have that first name there if we are on the signup so since the type is sign up due to our validation first name has to be there let's repeat that for the last name is equal to data. last name and we'll have to do it for all the other properties address one will be a value data address one exclamation mark we can then do city of data. City and you get the idea state is data. State postal code is data. postal code after postal code we have date of birth that'll be data. dat of birth with an exclamation mark SSN is data. SSN email is data. email and finally password is data. password for those two we don't have to add the exclamation mark because they will have to be there anyway even if for sign in and now instead of passing the data we can pass this newly formed user data object letting typescript know that what we pass into signup will surely have those values and now we can go into the sign up for Rams and we'll have to get rid of all of these question marks at the end because now for sure we know that they will be there if we do that our Dua create dalla customer will stop complaining because it knows it's getting all the data it needs to successfully create a dalla customer and with that my friends we are successfully creating a user account as well as a bank account and adding them as documents within our database this has been great success so far or it will be great success once we successfully tested so let's give it a shot I will close all of the currently open files go to app right database and I will check whether I currently have any users in the database and if you check it out we don't have any user accounts which is good because so far we didn't even have the function that would generate new documents but we did save some users into this session it looks like somehow some of you already found the link to the application which I'm current recording which is quite interesting unfortunately I'll have to delete all of you guys so you can properly test it with new accounts that will now get added to the database so I'm just going to go through all of these accounts and delete them you can repeat that process for all of your accounts as well and all users deleted and we are ready to give it a shot we haven't tested our application in so long as we've been just working within our code so it's possible we'll have to fix a couple of Errors first first we have to select the Dua environment either sandbox or production if you're still not sure why we're using dalla let me take some time to explain it once again played and dalla both deal with financial technology but they focus on different things played is all about connecting apps with your bank accounts making it easy to access account info and do things like verify identity think of Blade as a middleman making it easier for apps and Banks to Share info securely Dua on the other hand helps people and businesses send receive and request payments specializing in realtime payments so while played act as a bridge between apps and banks for accessing financial data dalla is more about facilitating actual money transactions you would choose to use dalla when you need to integrate Payment Processing into your application and that's what we are doing here and to fix this error we'll have to create our Dua balance sandbox account the link to that will be down in the description so here you can enter your first name last name as well as your business name if you don't have a business feel free to enter JS Mastery or anything like that you can also enter your job title or just say developer email password country and create an account once you do that you'll have to verify your email and once you do that you'll be redirected to the overview head over to the left sidebar and click applications and then copy the key and the secret go back to envs and paste them right here first we have the key then we have the secret after that we can also add a base URL this will be a static string of https col API - sandbox. walla.com make sure to spell it properly and then dalla EnV will just be sandbox great moving back to our application we can reload and here we are we are redirected to sign in but specifically we want to head over to sign up before we continue with the sign up uh let's just hide this connect back initially we have added it here before just test so back in our OD form here we can bring back this if user then show the plate link because first we want to create our account and only then do we want to connect our Dua and plate accounts to it now back on sign up we can only see the signup form and only after we complete all the fields we'll be able to link our bank account look we wrote a lot of code haven't tested it in the meantime something might break but let's give it a shot and then we'll buug on the go I'm going to enter my name my last name as well my very cool address and here at this point we have to start being careful with what we write okay uh address can be anything first name last name sure city as well can be anything but moving forward state has to have two characters postal code also has to be around five so to be 100% safe that you have valid data here I I would recommend that you copy the same thing that I have NY for New York 1 2 3 4 5 you have to enter a real date of birth let's go with something like 1990 and we can do first of January SSN I believe in this case will need to be four numbers let's do it like that for now you can enter your email and you need to enter a nine character password and click sign up it's loading and it looks like it has failed somewhere if we open up the terminal there's an error saying invalid document structure and specifically that's coming from ight and it's telling us that there's an unknown attribute of state so going back to our aight dashboard going to databases Bank users and then attributes we can search for state and it looks like I forgot to create it so let's just add a new attribute of state of size 1,000 and required while we're here we might as well also remove the existing documents or odd sessions that way we'll be able to try again we'll also have to remove the customers from Dua as it looks like it succeeded in creating one so let's deactivate the customer and and deactivate and now we can give it another shot I'm going to speed up the process of filling this out for you and let's try to sign up one more time it's loading and going to our terminal it looks like we got another invalid structure this time pointing to a field of password oh and I think I know why this one is happening if we go to our user. actions. TS and go to the signup form we're accepting all of the data Here sign up forams and that contains the password as well but when we're initially passing the user data to the user account right here we don't want to pass the password in create document we don't want to add it there so to ensure that happens that the password gets left out what we can do is instead of destructuring the values here we can destructure them right here at the top by extracting the password first and then spreading out all of the other properties that will look something like this and it will be of a type sign up perhaps now we can remove the password from here and I believe everything should be good as now this user data contains everything besides the password as we have already extracted it from the user data and then spread out other properties that's a pretty cool tip now very quickly let's go back to dla and let's see if our user has been reactivated it looks like they have been so we'll have to deactivate that user again just to be sure and we can repeat the procedure on aight this only happens while testing now just before we give it a final try I remembered there's one more thing we have to do and it is right here under played link we never uncommented this part of the code right here exchange public token this is that big function we have created in lib user actions that's one thing and the second thing is within user actions where we have a client name here we're referring to the user.name but this user is coming from the database and instead of that name which is there for the session user the database user has either first name or last name but not a name so if we want to do a client name we have to do it like this a template string of user. first name and we can also attach a user. last name to it great with this in mind I hope everything will work so let's give it a shot I'm going to click sign up it's loading and our connect button has a nice shade of BL blue which means that it's clickable and it should allow us to connect the bank now I want to pause here for a second and tell you that we have implemented a lot of code and that we had to be precise while implementing it so I'm not saying that's the case but it is possible that for you it didn't work automatically if it did that's great if not let's figure it out first you can open up your terminal and see if you have any immediate errors they should tell you what's wrong for example if you're missing an aright field or if maybe you misspelled the way that you called a field within aright and then within Visual Studio code another reason why it couldn't work is because maybe you already have an existing account that you forgot to delete either from aight on session or from Dua so you can deactivate the account there and for any other errors I think now is the perfect time for me to push my code without the EnV file of course and that way you'll be able to compare your and my code line by line and ensure you can proceed and follow along so let me just go right here to get ignore and I'm going to add a EnV at the top so it gets ignored a commit message can be something like Implement play link and dalla there we go that's good played link and VOA commit I'll make sure to remove the EnV later on so you guys don't get the keys even though it's all sandbox so I'm just messing with you now that I've done that I want to give it a shot and see if the code that I pushed actually works so if I click connect bank it's loading and we get this beautiful plate popup allowing us to connect our account so let's continue and would you look at this these are all instit tions that we can connect with these are the most popular US Banks but of course there's many many more for different countries this is a Sandbox account though and we have connected for the US market so for now we have the US Banks I'll choose Chase and continue to log in now you'll have to enter your username and password and these are coming from plates dashboard if you go to the left side developers and then sandbox it's user good and pass good now one very important thing is to also go to Integrations and search for Dua and here you need to press enable this will enable that integration and allow you to authenticate your customers's bank accounts for dalla so let's click enable and now we can proceed with the sandbox username and password so let's do user unorg good and password unorg good and sign in get code submit and you can select the accounts you want to connect with I will go for checking and saving and I'll take all of these boxes and click continue yes we have read the terms and condition and we want to connect account information almost done and success your account has been successfully linked to Adrien JS Mastery let's continue and we we have been redirected to the dashboard that is great we're pulling all the data from our user account Adrian JS Mastery and we have connected our first bank account but right now there is no way for us to actually see that we have connected it this right here is a fake number we have hardcoded it before and this right here is a fake total current balance so now is the time that we fetch the data from the bank account display the total current balance and also render all the recent transactions let's do that next things are about to get exciting instead of immediately diving into recent transactions why don't we go ahead and pull any kind of data from our bank we can do that if we go to app rout and then homepage here we have a total total balance box and we're passing a fake total current balance so what do you say that right here at the top of our homepage we fetch real banking data I'm talking about this thing right here and just to show you if we go to our databases and then Banks you should be able to see a complete Bank connection data with the account ID bank ID access token even funding source URL sharable ID and the user de connecting it to our user account all the data is here in aight cloud and now we want to fetch it into our application and we can do that by creating a new actions file right within lib actions called bank. actions. DS inside of here we'll have a couple of actions that will allow us to fetch only the data that we need from our connected bank account so in the read me of this project you can find the complete bank. actions. TS file copy it and paste it right here even though it might seem overwhelming you'll soon start to notice that basically the only thing we're doing here is mapping over the data and returning only the pieces of the data that we actually need on our front end so let me collapse all of the functions we have here get transactions we also have this get account get Institution and finally get accounts these are the four different functions we need and I'll explain them one by one very soon you can also notice that some code right here like this import get transactions by bank ID has been commented out as well as some code within those files I'll explain that soon for now it's important that you copy it just as it is from the read me of this project starting off with get accounts this returns multiple bank accounts belonging to a specific user let's see how does it work we first get all the banks from the database and by the way this function even though we're importing it we haven't yet created it so it doesn't exist so immediately after I explain how this works we'll go ahead and code the get Banks and get Bank within user actions moving forward after we get all the banks we want to get access to all the accounts within those Banks and this is an asynchronous action happening on multiple calls at the same time we don't have to fetch all the accounts from One bank and only then transition to fetching all of the bank accounts from another bank what we can do instead is start fetching all of the accounts from all of the banks at the same time and we do that using promis that all after that we get all the account data as I said the reason why I provided this right here is to just save us some time as the majority of this work is just accessing the properties nested deep within this data object accounts. response.data do account zero accounts response data item institution ID and so on and after we fetch all of that data what I do here is I simply map it to a simple to understand and simple to call object that has only the information we need such as the available balance current balance institution ID name official name and so on and we get it in camel case instead of this underscore format here as that is more JavaScript friendly Also let's fix this spelling right here it is sharable ID and after that we simply return it once we have all the data we can also get the number of total Banks get a total current balance by adding the total of all of these Banks and then returning all that data to the front end great so now that we have this get accounts function let's Implement two little helper functions that make it work get Banks and get Bank we can do that within user actions so let's scroll all the way to the bottom let's start with get banks by saying export const get Banks is equal to async function and it accepts a program of user ID to know banks for which user are we trying to get and that's if we type get Banks props and of course it's an aror function then we have a try and catch Block in the catch we can simply console.log the error and in the try we can get bags from the database by first accessing database from the create admin client by saying await create admin client and then we can get the banks by saying await database. list documents and want to list all the documents from the database with this specific database ID belonging to the bank collection ID and we can apply a query which we have to import from node app right equal user ID belongs within array user ID so this will ensure that we only fetch the banks belonging to this specific user this is how you do database querying in aight finally we can return a par stringify of banks. documents we can now duplicate this function below rename it to get Bank and from a specific bank which we can access by targeting a specific document ID we can extract some additional information so here everything is the same but we're getting a singular Bank from a database from the bank collection ID but we're going to Target by dollar sign ID that matches the document ID and that's of a type get Bank props and here we can return bank. documents zero so now we have those two additional functions that are going to help make our get accounts work after we have that we are ready to go back to our home page and put it to use so here we can say const accounts is equal to await get accounts to which we need to pass the user ID of a variable logged in dollar sign ID and we need to import get accounts from lib Bank actions then if we don't get accounts like this we can simply exit out of this function and not return the homepage as that shouldn't happen and after we have multiple accounts we can get further data for a Singler account by first fetching the ID of that account in the database by saying const aite item id here we can make that equal to in parenthesis ID as string or accounts data zero question mark. ight Item ID and instead of accounts data it's actually accounts question mark dot data and now that we have the aight ID we can say const account is equal to await get account inside of which we pass upright Item ID and this get account has to be imported from Bank actions we're going to look deeper into that actual function a bit later but for now it's important we have all the necessary data we need to show so first of all for the total balance box we can now pass the accounts question mark. data and I notice we're repeating that a lot like here as well so maybe we can put that in a new variable on top const accounts data is equal to accounts question mark. data that way it's going to be a bit easier to access data and we can use the same thing right here total banks will be equal to accounts question mark. total Banks and total current balance will be equal to accounts question mark. total current balance back in our application you can see that the ID is not defined right here and that ID should actually be coming from search prams in nextjs you get access to the search prams right here and then from search params you can further destructure the ID and the page because later on we'll Implement pagination and all of that is of a type search for Ram props and as you can see the app is now working and we seem to have 0 in our account in the right sidebar we can now also pass the accounts question mark. transactions and under Banks we can pass the accounts data question mark. slice and we can only show the first two cards and we can do that like this of course we cannot see it on mobile but it will be there on desktop while we're here why don't we also consol log the account's data as well as the account to see exactly what we're getting back so consol log I'm going to put it within an object accounts data as well as account let's check out what we get and I opened it up and unfortunately cannot read properties of undefined read reading the access token that means that we're having trouble accessing some data about our user and I also get an invalid query regarding a property of dollar sign ID interesting this makes me think that we're trying to query a user from the session instead of a user from the database because a user from the session doesn't have that ID and the user from the database does so let's quickly navigate over to user actions and specifically let's look into the sign in function if you compare the sign in to sign up you'll notice that in the signup we also store this session and it's important to store this session because otherwise when you log in it'll just immediately log you out so let's copy this session and cookies set coming from the sign up and let's put it in the sign in as well specifically right below this account we get the session create email and password login set it to cookies and then instead of creating another session we want to get full user information coming from the database and we can do that by saying const user is equal to await get user info to which we can pass the user ID equal to session. user ID and just a quick note here before we proceed make sure to put the user as the return within the part stringify and now this get user info which is a function that fetches a real user from the database not from the session is something we have to create so right on top of signin let's create a new export const get user info which is an async function that accepts the user ID as the first and only parameter and we can close it and make it of a type get user info props within here we'll have a very similar code to what we have in our get bank so we can scroll all the way to the bottom and we can copy the catch block from get bank and paste it in get user info the only difference here is that we're not listing Bank documents coming from the bank collection this time we want to get a user coming from the user collection ID and we're not querying it by the dollar ID rather we're querying it by the user ID which we compare with the user ID which we're passing through param and instead of calling it a bank it's a user and we're returning user documents zero so this is a function that returns a database user instead of a session user we'll also want to use this within the get logged in user as right now we're just getting the user from the session but now alongside getting this result from a session we can also fetch a real user from the database by saying await get user info to which we can pass the user ID of a value result. dollar sign ID and then we return that user now as soon as we do that everything will break that's because before in our session we were getting the user. name that combines both the first name and the last name but the user from the database instead has first name and last name variables or attributes stored separately so to fix that we have to go to the search and search for user question mark. name and you can see we have used that two times in the footer so we'll have to switch this over to user question mark. first name it's also possible that sometimes we called it with without a question mark yes we did four times it looks like so we have to change all of the occurrences from name to first name we can also do that here user. first name in this case we can also add the last name as well and right here when we show it in the cards instead of showing user.name we can do user. first name make it into a template string and then also render the user. last name right after it as before the name was combining both the first name and the last name and I believe that sometimes we also call the user a logged in variable so if we search for logged in question mark. name it looks like there is one instance and that is this one right here where now it says guest but here it's just logged in that first name now and successfully we're getting the user from the database instead from the session and you can see that here as well as here but the most important part is that now we're getting a total current balance that is not zero yep that's right if we go back to page and check out the conso logs that we wanted to check in the first place now if we scroll to the bottom we're getting plenty of Juicy data we get all the information about the account from the available balance to the current balance institution IDs names official names subtypes and more and we also get a list of Juicy transactions these are fake sandbox or test transactions created for us by sandbox plate so we can play with them so soon enough we'll be able to show them right here within the recent transactions but for now let's just fix one small bug and that is that we have only one bank account at least for now but here this donut chart shows three separate Banks this is still static data so let's close all of the currently open files and go over to the donut chart here we have to figure out how to map over our real bank accounts and extract the labels as well as the data points we you can do that by saying const account names is equal to accounts. map where we get each individual account and for each one we get the current name alongside the names we also need to get its balances by saying cons balances is equal to accounts. map where we get each individual account and for each one we extract account . current balance this gives us access to two arrays account names which we can use as labels and balances which we can use the data for the chart and now we have a single chart that says play checking which is the name of our account and it shows the total current balance after we add more bank accounts more parts of this donut chart will appear perfect now we can go back over to our homepage and remove this conso log it has done its job and we can scroll down and we can create a component that will render our recent transactions so let's go to components create a new component called recent transactions. TSX and run RFC right within it and then import it as a self closing tag recent transactions right here immediately we know that we'll have to pass some props to it so let's pass the accounts equal to accounts data let's pass the transactions equal to account question mark. transactions we saw all of them in that conso log and let's also pass the aight item id equal to aight Item ID and finally the page equal to current page now this current page variable we haven't yet created we only have page at the top but here's a little Pro tip everything that comes from search forams even though it sounds like it could be a number is actually a string so we need to create a new con current page and convert it into a number by saying page as string or it can be set to one by default and now we're passing over the current page so now let's go into the recent transactions and accept all of these exciting props we can do that by destructuring it getting the accounts we can get the transactions which by default can be an empty array if you're not passing any we get the app right item id as well as a page which by default can be one and all of that is of a type recent transactions props and now after a long long time of writing logic implementing Banking and more we can get back to writing some jsx to start forming the table for our transactions so let's turn this div into a section with a class name name equal to recent transactions right within it we can create a new header that will have a class name equal to flex items Das Center and justify Dash between within it we can render an H2 that will have a class name equal to recent Dash transaction Dash label and it will simply say recent transactions right below it we can also display a link component which we have to import from next link that will have an href equal to a dynamic template string of SL transaction Das history forward slash question mark ID so we're passing an ID parameter equal to aite Item ID and this is basically the ID of our specific bank account so for looking transactions for bank account played checking we can navigate over to see the entire transaction history this link can have a class name equal to view- all- BTN and it can say simply view all there it is now below this header we can create tabs tabs are layered section of content also known as tab panels that are displayed one at a time and this will be very useful if we want to switch between transactions history of different bank accounts so for example here we can have played checking and here we can have played savings so let's immediately add tabs to our application by pasting the command into the terminal MPX shat nuui latest ad tabs and we can copy the usage first copy the import right at the top and then copy the tabs we can paste them right below the header and indent them properly let's see how that looks like here we have account and password and you can see that works but in our case we want to pass the default value to to be equal to aight item ID so this belongs to one specific bank account and instead of 400 we can give it w- full to tabs list we can give a class name equal to recent Das transactions dtab list and we can create tab trigger as well as tab content from scratch so let's start with tab triggers these are the buttons that allow us to click and switch between certain tabs so there will be as many triggers as there are bank accounts so we can say accounts. map where we map over each account of a type account and we can have an instant return for each one so just put parenthesis here for each one of these accounts as I said we return a tabs trigger with a key equal to account. idid and a value equal to account. aite item ID and within it we can create a very simple bank tab item component so let's go to components and create a new bank tab item. TSX and this is a very simple component which you can find in this Project's read me copy it and then paste it here basically what we're doing is we're accepting the account in this specific aight item id we're checking whether that one is currently active and based on that active State we're showing a different class name we're modifying the URL based on the one that we click so if we're on the homepage it will have a special ID depending on which bank transactions are we currently looking at and now we can use that bank tab item imported from slbank tab item and to it we'll need to pass a key as we're mapping over it of account. ID we need to pass the actual account and we need to pass the aright item id which is equal to aight Item ID and now you can see this gray tab that currently only says played checking as that's the only bank that we currently have as we add more it will be very exciting to switch between the two and get completely different transactions for each one but now that we can switch between those different tabs it's time that we show or render the tabs content the meat of the table the transactions and we can do that by going below the tabs list and mapping over the accounts by saying accounts. map where we get each individual account of a type account and for each one we return a tabs content each tabs content will have a value equal to account. aprite item id a key equal to account. ID and a class name equal to space- y-4 and within here we can show some Bank information it'll be a very simple component similar to bank tab item so let's create it within the components folder called Bank info. DSX and you can find the bank info in the read me down below as well what we're doing here is we're getting all the account information checking whether it's currently active doing the same thing as before by modifying the URL if we click on it changing the colors but specifically we just have a lot of jsx where we extract all the information about a specific bank such as its subtype also its account name the account subtype the current balance and more so if I now save this and call this Bank info and import it from slbank info the only thing we have to do is pass the account equal to account as well as the aight item ID equal to aite item id which is the ID of the bank account and in this case the type of full as we want to show the full information and this is it this is what we were creating an icon a title the balance and the account type so as we switch between different accounts later on once we add multiple this part will also change giving us real-time data on each one of the accounts now comes the exciting part which is creating the transactions table so we can create a new component right here and we can call it transactions table. TSX where we can run RFC and we can import that component right below the bank info by saying transaction table coming from that/ transaction table the only thing we need to pass to it is transactions equal to transactions and now we can dive into the table and start implementing it of course we'll use a shat CN responsive table component which is simple Sleek yet it gets the job done so let's copy the installation command paste it right here import all of the components we'll need right at the top and we can also paste the usage by copying this table and pasting it instead of this div and we can indent it properly as soon as we do that we can see a very simple table of course this data is fake right here so we're going to make it real we don't need a table caption in this case but to this table header we'll give a special class name of BG Dash hash F9 fa FB I found this Coler to work good for the header and then in the table row we can decide which fields we want so let's give it a class name of padding X2 to create some space and the first field can be transaction we can also expand this a bit so we can see everything in one line after transaction we can have some more so let's delete the existing ones and create new ones 1 2 3 four five more we'll also need the amount of the transaction as well as the status of the transaction we'll need the date to the channel where we're spending that money and the category as well well the last two will be hidden on smaller devices so saying Max MD hidden as we don't have too much space for everything and now you can see some Fields appear right here now that we're done with a table header we need to focus on the table body where we'll display this actual data and this table will be highly customizable we'll be working with different colors depending on whether it's an income or e deduction we'll be checking for the status removing special characters from the name formatting data and time and more so let's remove this fake table row and let's create some rows of our own each row in our table will be one transaction so we can accept transactions through props by destructuring them and that's going to be of a type transaction table props and we can map over the transactions by saying transactions. map or we get each individual transaction I'll just shorten it to T of a type transaction and for each one we will open up a new function block for each transaction we have to get its status whether it is processed or pending and we can do that by saying con status is equal to get transaction status coming from lib utils where we pass a new date of t. date and if we look into this get transaction status function we're just working with dates a bit getting the current date and we're also trying to get the date two days ago as typically it takes one to two days to process transactions on this sandbox mode of course once you deploy to production it's going to take the usual time for a banking transaction typically that's about one working day so you can play with this and modify it as you will I left it about two days for testing so after we get the status we also want to get the formatted amount and we can do that by saying const amount is equal to format amount also coming from utils to which we pass the t. amount amount next we want to check whether it's a debit card or credit card transaction which we can do by saying const is debit and here we check the transaction or t. type is triple equal to debit in that case it is debit else we can duplicate it and if t. type is credit then it will be the is credit is true great and now we have all of this starting information needed to render different table rows for each transaction so right below we can return a new table row this table row will have a key equal to transaction or t. ID and we need to have a new table cell for each one of our table heads table head for example transaction has to be the transaction name table head for amount has to contain the actual amount status will contain status values for each transaction and so on so let's render the first table cell that's a table cell component within which we can render a div within which we can render an H1 and there we can render the transaction or t.n name if we do this you should start seeing a lot of new transaction rows appear and many have special characters which we want to remove in this case so I've created a special utility function which we can call called remove special characters and we can simply wrap the t. name within it and it will remove some special characters that looks a bit cleaner doesn't it of course we'll need to style it further but for now let's focus on the second table cell this one we'll check whether it is a debit and if it is a debit then we can prepend a minus sign before the amount else if it is credit then we want to show the amount and in other case we also want to show the amount the only thing that is different here here is that if it's a debit we are adding a minus sign before and that gives us all the amounts so I was wrong before when I said that is debit and is credit is referring to cards it's actually referring to the fact whether we are adding or subtracting money from our bank account one table cell below we can render the status so that's t. status status or no I think we have a status right here yep we're defining it as a new variable so that will be either processed or pending or in this case success or pending below that we can do another table cell where we can render the date of the transaction we can do that by calling the format date time utility function to which we pass a new date inside of which we have the t. date and we only want to get the date time only we don't want to get the full date format so we want to get something like this Wednesday April 24th at 2 a.m. and the last two which will not be visible on mobile devices that's going to be a payment channel so that's t. payment Channel and the last one is t. category so let's duplicate it and say t. category and save and if we expand our browser you should be able to see a Full Table Right Here categories range from travel payments food and drink transfer and more and channels are either online in store or other and very soon we'll further style art transaction table to look something like this we'll Implement these little chips for processing subscriptions deposits and more and we'll also color the backgrounds of each row whether it's processing successful or declined I'll teach you how to truly customize your tables but for now even this will do it we have a homepage that has almost everything on it it's looking great and we're fetching real data so let's finish styling the transactions table to complete the look and then we'll add a button to add additional bank accounts after our user has been onboarded initially after the sign up so continuing where we left off let's give our rows some backgrounds we can do that by giving it a class name and it will be a template string where we check if is debit or if the first character of the amount is equal to a minus sign in that case it's a negative transaction in that case we can give it a BG of hash FFF BFA and else we can give it a BG off in square brackets # F6 Fe F9 if I save this if I save this and reload you can see that now some of these rows have a greenish background and some of this where we're spending money have a red background this is looking good let's also apply some additional styles to any row and we can make it important and say over colon BG none and over should be lowercase other than that we can also give it important border dasb default like this so it will have a default border no matter the color let's also style the table cell by giving get a class name equal to Max dw- 250 pixels padding left of two and padding right of 10 this will create some spacing within this div we can also give it a class name of flex items Das Center and gap of three and we can also style the H1 by giving it a class name of text D14 truncate F that - semi bold and text- # 34454 so now the transaction which is the most important part is a bit more pronounced let's scroll down and let's style the second table cell by giving it a class name equal to padding left of two padding right of 10 font D semi bold that's looking a bit better and let's also make it a template string to make it Dynamic like this and then and we can give it some special Styles depending on whether it's a plus or minus so basically we can copy the same thing we had here is debit or amount is triple equal to minus in that case we can do something so let's paste that here within a dynamic block of code if that is the case text will be a color of half # F 04438 which is a red color and else the text will be of hash 039 855 which is a green color so now that will look a bit better with the background that we have great moving down we can style the next stable cell just by giving it a class name of padding left of two and padding right of 10 to give it some more space for the status and we can copy this class name and give it to all other table cells as well there we go now for the date we can also give it a m-w d32 because it will need some more space for the date for the payment Channel we can also say capitalize and give it a m-w of 24 and for the category we can give it on Max medium devices hidden so this will hide it on lower than medium devices now the next thing we can do is create this batch right here and this one too we can do that by creating a new component right on the top of the transactions table and we can call it const category badge as a prop we'll be accepting the category of a type category badge props and here we can return a div with a class name which will have that Dynamic CN coming from lib utils category Das badge within that div we'll have another div that will just be a self-closing div with a class name of also CN with size two in the rounded Das fo and below that div we will have a P tag that will have a class name of CN as well you'll soon see y with a text of 12 pixels and f- medium and it can say category now if we save this we can use this category badge just below in some of these table cells such as for the status so here we can render a self-closing category badge and we can pass a prop of category is equal to to status and we can also call it right here at the bottom for the actual category and to it we can pass category as t. category now if we call it you should be able to see that it will appear in two places here status as well as category badge which we cannot really see right now so if I expand it a bit there we go you can see that badge right here as well so now let's style it further depending on the Coler we're working with and this Coler will come from the transaction category Styles so each transaction has its own Styles so we can say const and these structure some values from transaction category Styles coming from constants where we go into a specific category or we simply choose a transaction category styles. default so this is something I've created before within the constants where we simply have different categories like food and drink payment Bank fees and so on and each one gets a different color in this case it's complaining about typescript so we have to say category as key of type off transaction category Styles this way it knows that we're passing category which will be one of these existing categories and then we can extract these four things from it border color background color text color and Chip background color so let's destructure them right here add commas and now we can add them right here as the second parameter of CN for the first div we can give it a border color as well as a chip background color for this inner div we can give it a background color and for the P tag we can give it a text color and if we do this you should be able to notice that success will now be green we don't have any other states right now later on we'll have pending and then you can notice travel is blue payment is green food and drink is red and so on and if I expand it this is our table looking great let's just quickly do something for the travel as well as I notice that we're missing a travel category so if I go into into the transaction category Styles let me show you how we can modify this I will duplicate success for the background color we can give it something like BG blue 500 for text it can be text blue 700 and then for the Border we can do some kind of a blue color let's do this one of # 0047 ab and this will be for the travel category if I do this and go back and fix this space right here this is now looking great now let's quickly figure out how we can add multiple bank accounts so we can then switch between different transaction lists right here on the homepage to achieve that we just have to use our played link component we have created and used on the onboarding we have to use it in a couple more places so first of all let's use it in our sidebar specifically if we scroll down here where it says user we can actually call the played link component coming from that/ plade link make sure that you use the one that we have created so this is the one coming from pled link and you'll need to pass the user is equal to user and with that we can go into it and notice that now we're not passing a variant so variant is now not the primary one but rather we have these different a ghost and a regular button so let's go ahead and style them together in the sidebar case we're not passing anything as the variant so we're looking at this button right here let's give it a class name equal to play link D default and it will also do the same thing it will be on click is equal to and then here we can have a callback function or we call the open function and as a matter of fact we can copy this over and move it to this button as well in the ghost variant but this time it will just have a variant equal to Ghost and the class name will be play link ghost next alongside simply saying connect Bank we can also render an image coming from next image we can give it a source equal to for slik SLC connect dbank . SVG with an ALT tag of connect Bank a width of 24 and a height of 24 finally below that we can render a P tag that will say connect bank and we can give it a class name of text- 16 within square brackets font Das semi bold and text- black-2 and while we're here here we can basically duplicate this image and the P tag and add it within the ghost button too but here our text will be hidden usually and it will show on extra large devices as we have more space to show it with that in mind we don't need this style string now that I notice it and you should be able to see this connect Bank button appear on the bottom let's give it a shot and let's try to connect a second bank account let's click continue let's go with Chase again continue use the user good and pass good credentials so that's user good and pass good let's continue and instead of checking I think we can choose some different ones like maybe savings and continue and going back to the app we can see success so if I continue and reload it looks like the account wasn't added and if you scroll up it looks like there's an error saying duplicate resource and this error seems to be coming from Dua right here creating a funding source failed duplicate Resource Bank or exists oh but it's possible that this error is actually right we try to add Chase again and we already have a played Chase account so if we go go back you can see that maybe it just took some additional time because our second account indeed got added we have played checking and now we have played savings too we can see a couple of things change first of all bank accounts number is two second of all in this donut chart we can out see plate savings and plate checking then we can see two cards on the right side and finally we can see two different different tabs on this tabs layout where we can switch between plate savings which should load its own transactions and plate checking but it looks like switching to Plate savings doesn't load up anything initially or it is possible that it just took some time to load them as when I switched to Plate checking to Plate savings now it works and you can switch through it very quickly this is looking great and now that we have this great looking recent transactions table why do you say that we use it within the transactions history that's a second page that can show us even more details so let's open up that page that is under transaction history and let's start implementing it to get started with our transaction history page we can first wrap everything in a section with a class name equal to transactions right within it we can have a div that will have a class name equal to transactions Das header and within it we can render a custom component called header box which we have created before so we can give it a prop of title equal to transaction history and we can also give it a subtext equal to see your bank details and transactions and immediately this will look much better see how cool it is to create a custom component system that you can then reuse on different pages below this div we can create another div that will have a class name equal to space- y-6 and another div within it that will have a class name equal to transactions Das account so right now we're creating a box that will show us our Account Details within it we can have a div that will have a class name equal to flex flex-all and a gap of two and within it we can have an H2 that will render the account name so to be able to get the correct Account Details we need to know which account are we trying to get the information for and we can get that from search for Rams by destructuring search for Rams from props and D structuring the ID and the page from it this will be of a type search param props then we can do similar things that we've done on our homepage where we're trying to extract Bank data we can essentially copy most of this information here and if we copy it one more time then it might be a good idea to turn it into a custom hook but for now I'll simply paste it here we're getting the current page we're getting the logged in user which we need to import from get logged in user we're getting the accounts by importing it from accounts and we need to make the function async since we're using a weight finally we need to import the get account and now if we scroll down within this age2 we can render the account question mark. dat. name and would you look at that it says played checking let's further style that H2 by giving it a class name of text- 18 f-bold and text- white that's much better and below it we can have a P tag that will show the account question mark. dat. official name so this will contain the full name of the bank account and we can give it a class name equal to thatt t-14 text- blue-2 so now this will make it look a bit better played gold standard 0% interest checking and below that we can show the same dots that we have in our bank card I'm talking about these ones right here so let's copy this P tag containing those dots and let's paste it below this spe tag and instead of 1 2 3 4 in here we can render the account question mark. dat. mask this will contain the last four digits in this case it's four zeros below this div containing the P tag we can have another div for the balance so let's create a div with a class name equal to transactions Das account Das balance and within it we can have a P tag that will say current balance with a class name equal to text D14 right below it we can have another P tag with a class name equal to text d24 text- Center and font Das bold and within here we can display format amount which is the utility function to which we pass the account question mark. dat. current balance and of of course let's properly close it right here and you should be able to see the total amount 100 and 10 and finally going two divs down we can render a section that will have a class name equal to flex w-f flex-all and a gap of six and right within it we can reuse our transaction table component so let's just call it like this and let's pass it the props it needs so it looks like it needs transactions equal to and that'll be account question mark. transactions and would you look at that we have our table right here which looks good even on mobile devices we can scroll through it with our finger and we can see the account information of this specific account later on will add the possibility to navigate from the homepage to the transaction history to check the details of each specific accounts and I think we can make it work right off the bat if we make this view all button work so if we search our codebase for view all you'll see we refer to that in our recent transactions and here what we're trying to do is we're redirecting to exactly this new page we have created with this specific ID with the ID of the bank that we're currently looking at so if we're on plate savings and if we click view all you can see that now we are looking at plate savings with a silver standard of 0.1 ending in 111 with a current balance of 210 and we can see old PL savings transactions let's also check that in full screen because it looks much better as most of the dashboards look better on full screen and if we go back to home and click view all on the played checking you can see that now we get the details and transactions for the played checking account this is great and I'm sure that now you can see that implementing this additional page of transaction history was much easier than what you might have thought and that's because we have laid out the foundation in terms of the design language with this header box and also we have created the reusable transaction table next let's focus on implementing my Banks this will be an interesting page where we can display different cards belonging to different bank accounts and as you might guess we'll reuse our existing card component so let's close this up and let's go to my Banks page and let's implement it by turning it into a section with a class name equal to flex a div with a class name equal to my banks that is wrapping yet another reusable header box this time with a title of my bank accounts and a subtext equal to effortlessly manage your banking activities let's see how that looks like there we go that is great right below it let's create a div to create some vertical spacing with a class name equal to space- y-4 and an H2 equal to class name of header -2 that will say your cards okay that's good right below it we can create a div that will act as the wrapper for our bank accounts so let's give it a class name of flex flex-wrap and a gap of six and within it we want to map over our accounts and that's going to be similar to what we're doing in the homepage we first want to get our logged in user and we want to get access to accounts so let's copy these two lines and paste them at the top of course make the page a sync and import get logged in user and get accounts now right within here we can first check whether we have the accounts and if we do then do the accounts. dat. map where we map over each account of a type account and then for each each one we return a bank card which we have to import from components bank card with a key of account. ID an account equal to a and username equal to logged in question mark. first name let's save it and would you look at that two new cards appear we can go into the bank card and instead of saying 1 2 3 4 we can access a specific account access the data and then access the I believe it was mask we use that within our transaction history right it is account data mask so here we can use that too or no in this case it's just account. mask because we're already destructuring the data so now this one is 0 0 0 this one is 1 111 we can also give this card A Min width so something like m-w Dash let's do 300 pixels or maybe we can do 350 let's see yeah this is way too much I think 325 should do the trick so that way they're all of the same width there we go this is better and as we used right here in the page Flex wrap they're wrapping which looks great for mobile devices but even a desktop they're going to wrap horizontally which looks great right now we only have two bank accounts and if you click on this bank account check this out currently it leads you to the homepage but we can make it lead to transaction history and now that I look at it on the homepage we don't want our cards to expand this much so going back I will remove this minwidth for now and instead of making the card point to the homepage we can make it point to a dynamic template string of transaction Das history slash question mark ID is equal to account. aite Item ID so now I can show you what I meant even from the homepage if you click on one of these cards you will be redirected to the account history for that specific account and if you go to my bank s you can also navigate to each one of your bank accounts by clicking on that account card let's go with this 111 and immediately we're there and we can also go to this one and that looks great too so as you can see this was easier than you might have anticipated but on the design we also have this line or at least we should have the link to copy the ID of this account in case you want to share it to a friend so that they can send you some money so going back to the bank card right here at the bottom we can add the ability to copy that ID so only if show balance is set to true then we can create a new component called copy. TSX and inside of here you can copy and paste the copy code from the readme of this project and the reason why I'm giving this to you is because it contains some svgs which would be very hard to write manually you never write svgs manually basically the only thing that this is doing is it copies the ID to the clipboard so now here we can display a self-closing copy component which we can import from that/ copy and as the title we'll pass it the account dot or question mark dot sharable ID so if we go back check this out the copy link is here here but unfortunately we cannot see the ID so if we go into the copy we have the button here and then we have this P tag with a text black so let me see if I type something here like test will it show it indeed does show so that means that this title is not properly being read as we pass it here sharable ID let's see why our account doesn't contain a sharable ID as it should be there we're calling this bank card from a few places and we are passing the account this is on the homepage but specifically here from the right sidebar we are also passing the account so let's simply consol log the account right here within the bank card it's a server component so it should appear here and it looks like we have a lot of stuff and one of these things is indeed a sharable ID but for some reason it's not getting pass to copy as a sharable ID so let's copy the title right here console.log title this will be on the client side so if I go here and inspect go to the console and the title is undefined and I just noticed that I misspelled the sharable ID right here so the way we're saving it into the database is wrong it's sharable ID we definitely have to fix that but for now I will just pass it like that there sharable ID that is misspelled so if I do it that way you can see that now it appears here so make sure that wherever you're adding that sharable ID it has to be spelled properly for the time being I'm going to leave it as it is and now we can copy the ID of each bank account which will be incredibly useful within the transfer funds page that is a very exciting page it is basically a very detailed form that will allow us to choose your own bank account from one of the attached accounts add a note and then add back details of the recipient and the amount so you'll be able to transfer money from one account to another so what do you say that we implement this form right here that we can see and then we can hook it up with the functionality and make it work this is the last big feature in our application so we can close all of the currently open files and navigate over to the transfer page right within the transfer page we can turn this into a section and we can give it a class name equal to payment Das transfer and within here we can render a header box which we can import from components header we can pass it a title equal to payment transfer as well as a subtext equal to please provide any specific details or notes related to the payment transfer and save this is looking better already and right within it we'll create a new section with a class name equal to size- fo and padding top of five and here we want to create a new component a second form the reason why we don't want to just start creating a form within here is then this page wouldn't be able to be server side as forms require interactivity which require to turn it into a client side component so what we have to do here is go to our components and create a new component called payment transfer form. TSX and this is the second form we'll create alongside our existing o form remember when creating the OD form we almost had the entire master class on how to work with chatsi and forms custom inputs and more we also learned about initializing the form using the used form from react hook form and more so what we'll do for this form is you can find the complete file in the read me of this project copy it and paste it here after you paste it you'll see that this is a long form about 250 lines of code now immediately if you've been following along carefully you'll notice one thing that jumps out and that is that here we're not reusing our custom input field but rather we have all of them coded separately one by one and I have purposefully left this here for you to see the difference and maybe just maybe give you the opportunity to refactor this to use our custom inputs for example here you can see a sharable ID you might want to use a custom input here and then refactor that it's up to you either way is fine for now I will leave it like this and if you want to you can practice a bit more to turn all of these into reusable custom inputs I think you can definitely cut about 100 lines from this file just by doing that now let's scroll to the top and let's see whether we have all the Imports another file that is attached to our form is a bank dropdown so let's quickly create it by going to components create a new component called Bank drop down. TSX it'll also be linked in the read me of this project so copy it and paste it right here you'll notice that you'll have to install the select component coming from shaten so let's do that MPX shaten UI latest add select and also for the form you'll have to add a text area because we haven't used it before so you can install those two packages once you do that you can fix the import for the bank drop down and then we can Implement a server action needed to get Bank details for a specific account by going to lib user actions scrolling all the way down to the bottom duplicating our get bank and turning it into get Bank by account ID where now it doesn't accept a document ID it's accepting the account ID and that will be get Bank by account ID props then we query by the account ID and we pass the account ID as the variable with which we're querying we can also do a quick check and say if bank that total is not equal to one that means that we can return null as the bank doesn't exist so now we have have this get backed by account ID server action and that leaves us with only one error right here create transaction we'll focus on this later on once we can actually see our form so for now I want to comment that out and I want to comment out the place where it's being used new transaction right here this will be the last part of our course where I'm going to teach you how to make a transfer from one account to another one but for now let's actually use this form right within our page that'll be payment transfer form and it we have to pass our accounts these contain data for all of our bank accounts so we can choose from which one we want to send the money from to do that we can quickly jump into the homepage and we can copy this logged in and accounts as well as this no accounts return and accounts data as this right here will give us access to the accounts data we need we can also make this transfer async as now we're having some await fetches here and we can also import these two server actions we have created before you can see how simple it is now that we have already done it before and now we can pass the accounts and make it equal to accounts data if you save that you should be able to see a form that looks great on mobile devices and since this is a dashboard type of an application it looks even better on desktop the only thing that's looking a bit weird is this select Source Bank which is kind of missing the background so let's quickly go into the backd dropdown and this file is basically just a glorified shaten select component where you can choose between different bank accounts we have two so right here under select trigger let's give it a BG of white and also under select content we can also give it a BG of white if we do that it's going to look more similar to other inputs and this will look much better so from here you can select a Source Bank you can also enter other information such as transfer node the email address and most importantly receivers played sharable ID and then finally the amount you want to send over but for this to work we have to go back to our payment transfer form uncomment everything that has to do with create transaction at the top as well and we need to create a new file called lib actions transaction. actions so let's do that right here in lib actions transaction. action. DS and in this case we need a create transaction server action so let's create it by saying export const create transaction which is equal to an async function that accepts the transaction or at least the transaction data that's going to be of a type create transaction props we can open up a new try and catch Block in the catch we can consol lock the error and in the try we can get access to the database by calling create admin client and once we have that we can create a new transaction in the database by saying await database. create document and we have to pass first of all the database ID and we need to get those things from environment variables I believe we have already used that within user actions yep here they are so let's copy those envs use them right here at the top of the transaction action file to and first we need to pass a database uncore ID then we have to pass a transaction _ collection _ ID then we need to get the ID from node aite and call the unique ID to generate a new ID and finally we need to form an object where we Define some additional data like the channel of Online category of transfer so we're defining our own category and then we can spread out the rest of the transaction data but first of all you'll notice something interesting and that is that here we're not referring to the bank collection or the user collection we are referring to the transaction collection and that's a special collection which we haven't yet created within aite so let's do that now let me just first import it properly here transaction collection ID _ transaction collection ID I think we did add that environment variable within our envs yeah that's correct it's here but we didn't yet Define the attributes that this transaction should have within the database so back in the ight dashboard let's go to databases Bank transactions and then attributes each one of our transactions will have a string of name size 100 and it will be required it'll also have the amount which will also be a string so let's do amount off a size 100 and required let's also do a channel so through which channel are we sending that money it's going to be online and that's also required next we have a category also of a type string so we can say category with a size of 100 and the required then we need the sender ID so this is the ID of the sender of the transfer let's make this a bit larger like 1,000 in case the ID contains multiple characters we'll also need a receiver ID so this transaction is kind of like a bridge between the sender and the receiver with a size of 1,000 and required and also we need a sender bank ID of size 1,000 and required and finally we also need a receiver bank ID with a size of 1,000 and required the last thing which could be optional is the email so the email that we can potentially use to send them updates about the transaction process let's make that 100 required and create and now now we have a transaction model for the transactions collection so we can finally create this new transaction and we will just return it by saying parse stringify and then pass over the new transaction that we have just created let's go back to payment transfer form and no longer should this be read let's just make sure that we're importing it from a proper file SL actions SL transaction. it's action okay let me see that if I go here it's supposed to be transaction. actions so let's add an S at the end that's good and we can add an s in the import right here as well great and if I go back to Local Host I get this weird error which isn't telling me much but it's saying that it cannot resolve FS which stands for file system and usually that can be found in node applications or any kind of server applications so that makes me think that oh I forgot to make this file a use server so server actions file if we do this now create transactions a server action and no longer should it complain and as you can see our home page is looking great let's move over to transfer funds and I I believe we have everything we need to send some money so let's try sending money from one of our accounts to a different one let's send money from PL checking to PL savings by copying this sharable ID going to transfer funds I'm going to add a Noe saying test transaction or test transfer I'm going to enter the email address paste the sharable ID and enter the amount let's do something like 10 bucks and click transfer funds now in this case it says that I didn't select a valid bank account and I think it's saying it because we need to add decimal points too so I'm going to add 10. and I'll click transfer funds one more time no more validation errors and looks like the form got cleared and we got redirected to the homepage which is always a good sign and even after reloading unfortunately nothing seems to be happening here well taking a quick look at the transactions collection in aight database we can indeed see one document test transfer of the amount 10 which is a transfer from sender ID to receiver ID sender back receiver back everything looks good here so the ight part is good but the plate stuff is not good and I think I know why back in back actions we have commented out the part where we fetch the transactions by bank ID but even though we're not fetching them yet they should have been sent right because here we're creating the app right transaction but just above we're creating a real transfer using Dua so how can we verify that a payment has indeed happened well let's go back to dwala dashboard here under transactions I would have expected that some of the transactions will appear here but that doesn't seem to be the case rather you have to go to the customers and then enter a specific user in there you can see all of the transactions and I did add to additional ones as I was testing so now I have three in your case there should be one you can see all the details about that transaction so what we can do next is go to bank actions uncomment this get transactions by bank ID and also uncomment the part where we call that function which is right here here we try to get transfer transactions from aight so let's go to transaction actions and let's Implement that function that allows us to fetch them we can start by duplicating the create transaction just below and we can rename it to get transactions by bank ID and also the props will be get transactions by bank ID props instead of the transaction we get the bank ID as the first and only parameter and instead of creating a new transaction we want to fetch some transactions first of all we want to send sender transactions so we know which transactions did we send so sender transactions are the transactions where we try not to create the document so let's delete that rather we call the database. list documents first we have to add the database ID specifying which database we want to get documents from then the transaction collection ID from which collection and then we can form the query. equal where we're comparing the sender bank ID if it's equal to the bank ID we want a query 4 and of course we have to import query from node aite and this bank ID has to be destructured right here at the top so it has to be within an object sign great now after we get send their transactions we also want to get rece receiver transactions so we can duplicate it and say receiver transactions we're going to also check for the same bank ID but this time we're going to compare it with receiver bank ID make sure to spell it properly and once we get all of that we can merge it together by saying const transactions is equal to an object where the total is equal to Sender transactions. total plus receiver transactions. total and as the second parameter we can pass all the documents by combining it into an array and spreading both the sender transactions as well as the receiver transactions right within it in this case we want to spread the documents of both of these so it will be data. sender transactions. documents and also do do do receiver transactions. documents and finally we can return par stringify transactions amazing now back in bang actions we now have access to this function we are calling it here which is giving us access to all of these transfer transactions and the last thing we have to do is when we're mapping over these transactions we have to add them to the list of the old transactions and we can do that by uncommenting this line that says const all transactions are the existing transactions all of the sandbox fake ones plus the transfer transactions both the sender and receiver ones we sort through them and we send them over to the front end great so now if we go back to the homepage would you look at that I have three processing transactions in your case you should have one that we're done right now and there of a category transfer now keep in mind your bank balance won't change yet it will take one to 2 days for the transfer to take effect exactly as how real Bank transfers work and if we switch over to Plate saving you can notice that here we also have the new transactions but this time they're green as we're adding adding money to the savings account and sending it from the checking account job well done now another quick Improvement we can do is adding pagination to our recent transactions list right now we have too many nobody wants to low that much or look at that much so let's Implement pagination right at the bottom of recent transactions below the transactions table we want to create a new component so let's go to the components and create a new pagination dtsx and we've implemented pagination on many videos in this channel but we have explored absolutely all advantages of doing service side pagination and filtering within this video build a car showcase application so I highly advise you to check it out if you want to improve your server side rendering filtering and pagination game with that said you can find the complete pagination component in the read me of this project so copy it and paste it here it's basically two buttons that when you click them they modify the URL bar that then contains the value of the page right there I'll show you how it works as soon as we import it within recent transactions so let's import it right here pagination coming from pagination and we'll only show it if we actually have more Pages than one so we can comment it out for now and we need to do some math regarding Pages first we need to decide how many rows will we show per page so we can say const rows per page and that will be equal to 10 then we can do the math and figure out how many total Pages there are by saying total pages is equal to math. seal and then we simply want to divide the number of transactions so transactions. length with the rows per page that's going to give us the total number of pages next we want to kind of take a span between one point and another point A and B to figure out which segment do we want to show like say you have three pages from 0 to 10 from 10 to 20 and from 20 to 30 you want to know on which page you're on and we can do that by getting access to the index of the last transaction you've showed on the previous page and the index of the first transaction of that page so let's get access to these indexes by saying const index of last transaction is equal to page times rows per page that's pretty simple right this is the last one we have seen so far then we need to get the index of the first transaction by saying index of first transaction is equal to index of last transaction minus rows per page and once you have that you can fetch the transactions which you want to show now so cost current transactions is equal to transactions. slice and you want to show the ones starting from the index of first transaction going all the way till the index of last transaction great and now we can go to the bation we can uncomment it and we can pass it all of these great props such as the number of total Pages equal to Total pages and the existing page equal to page so if we go back right now and we reload on our Local Host 3000 you should be able to still see all the transactions but now the pagination is there so how can we only show the transactions that need to be there for that specific page well we can do that by passing only the current transactions to the transactions table current being the ones we can see on the current page so current transactions if we save that we'll only be able to see 10 at the start there we go 10 and now we can use the next button to see the next then there we go a bit more green stuff right here that's always good and we can also go to the third page great and you can see the third page doesn't even have more than 10 so we know that we have reached the end and the next button is disabled and you can see that because the URL Bar says question mark page is equal to three and if you go back to two it will also switch to two great we can also use this pagination within the transaction history it's going to be even more useful then as this is a large table so let's navigate over to transaction history that's a page and right below the transaction table here we can basically show the same thing we have shown in the homepage so let's go to the recent transactions and before we copy it let's quickly fix this pagination by only showing it if there's more than one page and we can do that by checking for the number of total pages and and checking that it's more than one if that is the case we want to show a div with a class name equal to margin y of four and w- full and you can then put the pagination within it and now we can copy this part the total Pages as well as the pages math we have done before and we can paste it over within the transaction history right below the transaction table at least that's where the pation goes and the math will of course at the top of the page so let's simply paste it here but this time the transactions will be account question mark. transactions that's looking better and don't forget we also have to extract the page from the search per ramps and we're doing that right here at the top so that's good let's also import pagination from SL pagination or from components pagination and let's pass the current page to the pagination the current page in this factor is a numbered version of the search PR Rams which is just a string so we always want to do some math with a number so we can also use the current page here if we do that you can see the pation at the bottom but as before we'll have to filter out and only show 10 per page so to do that to our transaction table we can pass the current transactions these are only the ones we should be able to see on a specific page and immediately this will feel much better wonderful job pation is there too now one bug or let's call it a mistake I noticed is that if you go to my Banks you can notice that now it says Adrian here on top or maybe your name and also Adrian here on the bottom left actually that should say the name of the bank so let's make it say the bank Name by going to the bank card and then right here at the top instead of rendering the username we can render the account. name the name of the bank account that'll make much much more sense than the card that says Adrian and now we can see plate checking and plate saving looking good now let's go back to the homepage and let's add the last missing piece of the puzzle that is the categories right here below the banks if I open up the design and if we check out our homepage you can see my budgets and here we can see how much money we have spent on specific categories so let's go to the right sidebar and scroll all the way down below the bank card below these two pairs of parentheses and curly braces we can create another div which will act as the wrapper for our categories we can give it a class name equal to margin top of 10 Flex Flex D1 flex-all so they appear one below another and the gap of six we can then wrap it with an H2 that will have a class name equal to header -2 and it will say top categories as in you like this so much you're spending the most money on it so now you should be able to see top categories in the right sidebar and there it is and Bel below the H2 we can create another div with a class name equal to space- y-5 and within it we can map over our categories but where are we going to get these categories from to know how much we're spending well that will be one utility function that we have created before to which we can pass all the transactions so we can say con C categories of a type category count array is equal to count transaction categories coming from lib utils to which we pass all the transactions once you do that we can map over the categories by saying categories. map and for each category we can also get the index and for each one we'll return a new self-closing category component with a key of category. name as they're all unique and we'll pass the entire category of course this will break the app right now as we haven't yet created the category component so let's create it by creating a new category. TSX file inside of which we can run RFC and back in here we can import category from that/ category moving into the category we'll just have to write some light TSX code here to form the look and feel of it and I want to invite you to do this on your own so first let's get access to the category through props of a type category props and let's conso log it to see what we're getting or even tab script can let us know what is there by diving into the interface and we can see that we should have a name count and total count so let's simply render the categoryname and see if it's there right now we don't seem to be getting any categories so what we can do is we can consol log categories right here at the top of our right sidebar this is a server side file so we should be able to see them here as soon as we reload the page and it looks like we get back an empty array let's see what that is about maybe the list of transactions we're passing to the right sidebar was the mock list that we created before let's see we're calling the right sidebar right within our homepage and to it we're passing accounts. transactions instead it should have been account. transactions that is much better so now if we close this I don't think we even need to conso log it immediately we get a list of four of the most common categories that we spend money on travel food and drink transfer and payment so let's remove the console log go into the category and you can replicate the UI that you see on figma this is the one I'm talking about so it's a rectangle with an icon with some kind of a slider component going until the end and let me give you a hint that will actually be a progress component coming from shaten and then you can enter some kind of money left right here for how much you want to spend on all of this is coming from the category itself in this case since we already done a lot of work in this video I'll provide you with a complete category in the read me of this video but of course I invite you to coded your yourself first and since I've imported it I'll also have to add a shaten progress so let me do that by running shaty nuui latest add progress and once it's there everything should work flawlessly it got installed but I noticed that here in this file we're using export const not expert default again it's either way but whatever you choose you have to import it in the proper way here so since the import is the default import we can just export it at the bottom as the default export by saying export default category that should resolve the latest error that I can see here and we get a beautiful top categories part but we seem to be missing some sliders here what's up with that you can see that chat cen's progress component is complaining about not wanting the indicator class name only just a single class name and this is the perfect opportunity for me to show you how we can further style shatan components I'm going to dive into it and I will accept an additional prop of indicator class name and I will add it to this progress primitive indicator by wrapping this this with CN passing all of this as a regular class and then as the second parameter we can render the indicator class name if you do this some of these additional Styles will add the progress and make it look exactly how we want it to look this is great and our app is looking amazing and what's always the last step it's deployment yep that's right we've reached that point in the video this was a long one but if you're here you've made it if you stayed until the complete end you are in the minority it means you're serious about learning and improving your development skills so leave a comment down below and let me know but with that said let's proceed with the deployment I will do one final commit and say something like finalize the app here we Implement everything else from the latest commit so let's press commit and let's sync the changes once you do that you can head over to ver.com as you can see I have many projects right here some of which are YouTube videos in the making such as this portfolio website which is coming soon some of them are projects that our own entire development team is working on such as this course platform that we just recently updated this is how it looks like I hope you like it and I hope that it feels great I'm looking to add some freee riew features soon enough but yeah this is a pro platform where you can watch the latest nextjs course which I would recommend if you want to dive deeper into server side rendering and um yeah we've spent a lot of time building it and I would love it if you would check it out other than that on versel we also have some projects from teams and individuals attending the master class which is our four month boot camp where we prepare developers to land high-profile development careers with that in mind let's just add a new project for what you've been working so hard on this video I'm going to add a new project and I'm going to import it straight from a get repo by clicking import if it's not here you might want to push it like we did at the start of this course it's banking with a framework preset of nextjs and the last thing we have to do is modify the environment variables thankfully we've been keeping good track of them so if you go to your codebase go to envs we have next aright played dalla and more for now we can basically copy all of them and just paste them all here the only thing that we'll have to change later on is this value of the next public site URL as we don't know what that will be yet so we'll have to do it after the first build so let's scroll down and let's click deploy fingers crossed it gets deployed properly the first time and I'll be right back in a minute and it looks like typescript gave us an error and that's okay typescript is always here for us to save our ass but in this case we have purposely left sharable ID misspelled because we have misspelled it once again before so we love working with typescript during development but we can now just suppress its warnings during build you can do that by going to next. config.js and here you can say typescript within an object ignore build errors set to true as well as es lent ignore during builds is set to true as well and now you can simply push that once again by going to source and then saying modify next config to suppress typescript during build commit and sync changes as soon as you do that your app should try to redeploy on its own so if you go here to projects you should be able to see Banking and you can see building once again this latest commit so let's wait until it gets built or maybe until it fails one more time and it looks like it broke one more time which is totally okay it is a very big application and this is our first real production deployment or build so it's completely normal first of all two things we're missing the century o token We'll add that later on once we fully and successfully deployer application but second of all we have another issue an error saying Dynamic server usage route transaction history and all of the other routes couldn't be rendered statically because because it used cookies and then it points to this error message the fix for that could be to go to the layout this root layout right here and at the top add another directive export cons Dynamic is force Dynamic so this will always try to get Dynamic data when it can and therefore it will not try to render it statically okay so this is just one quick push which we can add here and say add Force Dynamic and let's see if we have more luck with that as before a commit will trigger a redeployment so let's go to Banking and you can see it is building one more time and it got deployed that's great so let's do two quick things before we check it out and that is go to project and click visit this will lead you to your url in this case it's a banking jet. verell doapp so make sure to copy this URL without the signin part go back to verell to your project go to settings and then environment variables and you'll have to modify this next public site URL from Local Host 3000 to this new URL that you now own on top of that we'll also have to add our Central variable so go back to your code and go to this special Sentry Clic file and copy the token then create a new variable paste this as the value and the key is sentore oore token add it save it and then very important go back to deployments and redeploy the latest deployment let's give it a minute and after that we'll be able to check our app on your own domain in its full glory and we are live instead of visiting this specific deployment just go back to your banking project and click visit and here we are we are live I even forgot how I sign in and sign up look like as we haven't visited them in a long time so what do you say that we give it a shot and test our app one more time but this time on the deployed version I'll enter my name and my last name here you have to keep in mind that we are still using the same database and the same API Keys as in deployment so you'll have to use a different email and name I'll add atrian and let's do jsmm that's a new one or let's do JSM Pro as there's a lot of news coming to the Pro platform let's also enter a new cool address with a New York City address in New York 1 2 3 4 5 let's do 1985 1 2 3 4 and I'll enter some kind of an email let's do [Music] a G.C that's a fake email but it will do for now and I'll enter my password oh it actually recognizes it's a fake email let's do the.co immediately after we are redirected to the second part of the onboarding which is the screen where we can link a bank account so let's do just that we can continue with played I'll choose Chase and I'll log in with a user undt good and passor good as well as that was provided to me in my sandbox I'll add a played checking accept all the terms and conditions like I have read them and continue immediately after we get redirected back to our homepage the categories and bottom right are looking great the my Banks looks good too we can see only a few transactions for this account which is good we can navigate over to the transaction history of this account and see all the sandbo trans actions with full pagination we also have the my banks part where we can see our existing bank account and here is our glorious transfer funds page where we can send funds to another account right now we only have one so we won't be testing that right now but if you want to you can also connect multiple accounts through our connect Bank model and of course it looks good on mobile devices as well if I navigate to my Banks looks wonderful and transaction history is also good with your finger you can move through the table and see other fields this has officially been the most complex course we have posted so far I hope you enjoyed it we used a lot of great software throughout such as aite for our database Sentry for tracking and session replay and don't forget we have also done a lot of work with shat CN typescript and more with that in mind if you came to the end of this video you truly are the perfect candidate for the ultimate nextjs course if you haven't taken it already I highly recommend it in there we dive deeper into server actions deeper into creating reusable forms different types of data fetching and more so a lot of exciting stuff is covered and we build an app that is maybe even more exciting than the banking app it is the modern stack orlow clone it has AI code blocks Community recommendation algorithm tagging system fully server side rendered and it gets 100% on All Points within web vitals not to mention that we have recently updated our course platform so now it feels and works even better we even have some free lessons so if you want to you can go ahead and check them out with that in mind thank you so much for watching and have a wonderful day the existence of react native makes react one of the most valuable skills to have it's crazy that about 75% of your knowledge from learning to make websites can carry over to building mobile applications that's exactly what I said in 2023 and it's more true now than ever before you may not believe it but what we do now in nextjs we can also do in react native 2 same file-based routing structure API routes and even react server components so hi there and welcome to a brand new Ultimate crash course where you'll learn the foundations of react native the newest features it offers and also deploy a Sleek full stack app using it the first part of this video is the ultimate crash course on react native we'll start by going over the benefits of using react native and why it has become such a popular choice for for developing both IOS and Android applications next we'll dive into Expo a tool that lets us get our application up and running quickly and easily after that we'll cover the fundamentals of react native we'll discuss its different elements how it compares to react GS as well as nextjs code structure file based routing styling and much more by the end of this course you'll have a great understanding of react native and you'll be able to create your own apps using this powerful tool alongside this video in the description below I've also prepared the ultimate react native guide that covers everything you need to know to become a fantastic developer the guide covers the complete react native road map prerequisites and essential react native components and project ideas you can build and deploy to get a job you can download the guide and use it as a reference whenever you're unsure what to do next of course the guide is completely free and once again the link is in the description immediately after I'll put your skills to the the test in the JavaScript Mastery Style by teaching you how to build and deploy a complete full stack react native application that's the only way to retain and expand on your knowledge the application you'll build is called Aura a full snack platform to share AI generated stock videos with a visually appealing onboarding screen robust authentication system including both signin and signup screens Dynamic home screen showcasing the latest videos in an animated flat list with a comprehensive list of all videos with playback pull to refresh functionality full text search capability with a dedicated search screen tab navigation for seamless browsing a post creation screen where you'll learn how to upload videos and images and a profile screen offering detailed insights into your account this eight screen app for sure has to be one of the best YouTube apps you can build with react native you won't need any previous react knowledge rather while building this you'll learn basic elements like view touchable image flat list scroll view safe area view text input and status bar animations using animat table responsive design styling using stylesheet and tailin CSS file-based and dynamic routing using nested routes and layouts Tab and stack navigation custom Hooks and fonts video players file Pickers professional code architecture and a backend using aite an open- Source platform that lets you add o database storage and more so you can build powerful full stack applications before we dive into the crash course let's first create an account on aight in the description down below you can find a special link that will allow you to follow along and see exactly what I'm seeing in this video so you won't get stuck click get started sign in with GitHub and that's it now let's dive straight into the crash course before react native developing mobile applications for multiple platforms was hard you had to write separate code bases for each platform which was slow and expensive but with react native you can write a single codebase that works on both IOS and Android which saves time and makes you a more efficient developer one of the reasons react native has become so popular is that it allows you to use native components which results in better performance and user experience and it's not only me who thinks that way big companies like meta Discord Microsoft Tesla Amazon Airbnb and even Call of Duty use react native to build their mobile applications it's gotten so good that you'll see only a few people fluttering these days on top of the crossplatform compatibility and Native components the benefits of react native are also hot reloading which lets you see the changes you make in real time speeding up the development process strong Community Support ensuring that the framework continually evolves and the improves and finally it's easy to learn if you're familiar with JavaScript and react you can quickly learn react native and start developing mobile apps which is exactly what we'll do today in this video we'll use Expo you're familiar with tools like create react app or V right Expo is just that only for react native applications it provides many tools and services that simplify development and help you build your apps more easily one of the biggest benefits of using Expo is its Simplicity with Expo you don't have to worry about configuring your development environment dealing with Native dependencies or installing huge Android Studio or xcode to get started Expo takes care of everything so you can focus in building your app Expo also offers pre-built components and apis for navigations gestures camera and maps you can write native code and compile and run it without any issues specifically it's over theair updates automatically publish new releases so the next time somebody launches your app your app will have the latest JavaScript code you push this usually requires a review from Google Play Store and Apple Store for each new update you have to bring but not with Expo in a nutshell if you're new to react native or want to develop your app quickly and easily Expo is the way to go it simplifies development and allows you to focus on building your app in this video we'll use the latest and greatest of what Expo has to offer they've recently launched a fantastic new routing system called Expo router it takes a different approach to handling navigation using a file-based routing system that is simpler more intuitive and very similar to how nygs handles routing Expo is also planning to add react server components soon this means we'll be able to do similar things that we do in nextjs from writing API routes to writing server components it seems like web and mobile development are going hand inand all thanks to Expo it's a no-brainer why big companies like Discord Burger King coinbase and Xbox choose Expo for their products and if you still think using Rea native CLI would have been better then you really need to think twice remember with Expo you can eject your app any time you want and then add additional features all right let's jump right into the exciting stuff we've already talked about the benefits and drawbacks of react native and how Expo can make your life easier now it's time to dive into the code and see how it works firsthand if you worked with reactjs before you'll find that react native uses a similar syntax but of course there's some differences you should be aware of let's explore the ins and outs of react native code examine how it looks and how it functions and compare it to react GS to help you understand the similarities and differences between the two by the end you'll understand react native components and how to use them when coding in react native you use JavaScript just like in react GS but instead of rendering HTML elements you'll be rendering native components so let's take a look at the basic react native component example we are importing two important components from the react native Library View and text and then we create a functional component called app that returns The View and text components wrapped inside the view comp component what's interesting here is that we're using jsx syntax which makes it easy to create and visualize our components in a more HTML like way let's take a closer look at the text component while in react we use P or H tags for text in react native we use the text component instead it's pretty straightforward the text component is used to display text in the app and you can style it using the same CSS like syntax as in react you can set the font size color and weight using the style prop react native also offers a Styles sheet utility allowing you to Define styles by creating a single JavaScript object this optimizes performance especially in larger applications and as Tailwind CSS is rising in popularity native wind came into the picture it allows you to write Tailwind like Styles within react native isn't that crazy it feels like we're working on a regular web app but we're developing a mobile app now let's talk about the view component think of it as a box or container that holds other components it's similar to a div in HTML but with some added functionality specific to mobile apps The View component is often used to create layout structures for other components it has many different props that can be used to control its appearance and behavior one thing to note is that the view component uses flexbox layout by default which makes it really easy to control how its children components are laid out so you can use flexbox properties like Flex Direction justify content or align items to achieve the layout you want but how can you add some interactivity to your react native app well get excited because we have some awesome components that can do just that these components are perfect for creating buttons links and other interactive elements in your app the first one on the list is touchable opacity which is great if you want to create a button think of it as a cousin to the button component in react but but with even more room for customization and flexibility the second one is touchable highlight which allows views to respond to touch in a unique way when touched the component reduces the opacity of the wrapped view revealing an underlay color and then there's touchable without feedback which is there if you need to create an element that is clickable but you don't want it to have any visual feedback when pressed it's especially useful for creating links or images that don't require any additional styling or effect apart from these touchable components there's also activity indicator which allows you to show a spinner or a loading indicator in your app button allows you to set properties like the title color and onpress function to be called when it's pressed but if you need more Advanced Styling or behavior you may find yourself using the touchable components more often since they offer greater flexibility the next component is the flat list which is perfect for rendering a long list of items that needs to be scrolled if efficiently it's like the map function in react but it has extra features like optimized scroll performance and item separation so when should you use the flat list and when should you just map over the elements in react native for larger lists with smooth scrolling go for the flat list for smaller lists map function will do the job scroll view is like a magic box that can hold multiple components and Views providing a scrolling container for them it's like having the Overflow scroll property of a div in HTML allowing us to easily navigate through a list of items or a large amount of content within our app by using scroll view we can make sure that the users can easily explore all the content making the app more intuitive and userfriendly there's also a safe area view which provides a safe Zone to render your apps content without it being covered by the devices Hardware features like the notch home indicator or status bar it's great for building apps that are supported on devices with different screen sizes and shapes while the default safe area view functions as expected for most cases it falls short for some users making it not the optimal choice so I consistently use react native safe area context to ensure content is contained within the safe area on any mobile device preventing overlap with notch or the Bottom bar in react native we can also use the image component to display images whereas if you want to display an image as background you can use image background the image background is specifically designed to display images as the background of a container allowing other components to be layered on top of it whereas just image is primarily used for displaying Standalone images both components can handle different image formats like pngs jpegs web PS and gifs and even gifs if that's how you pronounce it however believe it or not neither support svgs due to Native rendering limitations still you can use SV GS directly within Expo by using a thirdparty package like react native SVG react native also has many readymade components to display a model which looks something like this and an alert which looks like a typical alert and if you want to create a toggle in react native you can use a switch component one of the components that I frequently use is the status bar both react native and Expo have their own versions that allow us to control how a status bar should look like for each screen within our app and of course the list doesn't stop there as there are many components that help us simplify development but now that you know the most important ones let's dive into the action let's explore Expo and react native in more detail I'll teach you how to set it up what files and folders are involved and everything else that matters and as I've told you before I've also prepared a completely free ultimate react native guide download it from the description down below and use it as a reference throughout this video first we can create a bare minimum project starting off from bare Beginnings we can create a new empty folder on our desktop let's call it something like react native crash course and then drag and drop it into your empty Visual Studio code window once you're there open up your terminal update it if you need to by the way I'm using all my zsh for my terminal highlighting and within here we can set up our first react native project and as you might know if you've been watching some other JSM videos I always like to teach you how I would approach if I was doing this from scratch how to read documentation and how to truly become an exceptional engineer so if you don't know that about JSM you might need to subscribe and turn on that Bell notification to watch more videos just like this one with that said we are right here within manual installation within Expo docs the link will be in the description here we can see that the first step is to create an expo project by running the command MPX create Expo app so back within our terminal we can run MPX create Expo app and then we can type slash to create it in the current directory it's going to ask us whether we want to install the create Expo CLI to which we can say yes and it's going to download an install the basis for our react native project while it's doing that the next step is to install all the dependencies and we have to do this as we're doing a manual installation so we can say MPX Expo install and then we're going to install a couple of things Expo router so that we include the file based routing capabilities react native safe area context as I mentioned before this will help us make our app work on all devices with notches bottom bars and more react native screens which will allow us to navigate through different components Expo linking which will enable us to allow users to navigate directly to a specific screen within an app within an app from an external link such as another website or another app finally we have Expo constants that will give us access to a lot of the device information such as the operating system ID version and more and then the Expo status bar which simply provides a status bar component so let's copy it and then we can paste it right here within our terminal all of these packages are necessary for smooth functioning of x post file based routing system while that is happening we also need to set up the entry point so for the property main we're going to use the Expo router entry as its value in the packet Json the initial client file is app layout JS so let's copy this collapse her terminal and navigate over to package.json by the way what I've done just now is I pressed command p and then I started typing the file name and now by simply pressing enter I am in the file without ever touching my mouse opening the Explorer and then manually navigating to it that's just one of the many pro tips that I'll give you throughout this video so once again control or command p with that said we have the main right here which we want to override so the main will now look something like this Expo router entry and of course we want to provide a comma at the end now that we have changed the entry point we can use filebase routing similar to the one of nextjs so let's go ahead and copy the contents of the appjs file by pressing contrl or command a and then control or command letter C deleting this file and creating a new folder called app that will have a new file ofor layout. jsx and here we can paste the code that we had in the app before this will be the starting point of our application returning to the docs we need to modify our project configuration by Deep linking scheme in our app config so let's go to our app. Json by navigating to it and add a scheme right here and we can call it the name of our application such as Aura right here this scheme field is used to deep link Expo and react native applications it's a special technique that allows your app to be opened within a specific screen directly from a URL outside of the app such as from email web page or another app and as you can see in this file we also have a lot of other stuff such as the name which specifies the name that appears on the app's home screen and also here you can modify that to Aura or your own preferred app name we have the slug which is a URL friendly version of the app name once again we can have Aura right here we have the version the orientation some typical stuff we have the icon which you want to show the user interface style splash screen a path to the assets whether it supports tablet devices a specific setup for IOS and Android devices and additional plugins that you can add for example you can immediately see the Expo router we added before do you get it it's just a file with many configurations to improve our app we'll play with a few of these in a few minutes we can now proceed with the next steps outlined in the docs and compile and run our application we can now proceed with our docs I believe that our Babel config has been properly set up so we can immediately run our application typically it's just MPX exp poost start but you can also add a c flag which will clear all the previous cache so let's copy this command close our files open up the terminal and run MPX Expos start- C this command will download and execute the expose start command which will start the metro bundler and the JavaScript bundler that chips with Expo and you can see a few elements right here starting off with a large QR code and different shortcuts for various actions for instance to open up the app in Android Studio you can press the shortcut a and the same applies to iOS press R in the terminal to reload the screen or press J to open up the debugger we'll test a few of these functionalities as we start building our full stack app and as I mentioned before you don't need to rely on heavy tools like Android Studio or xcode instead we'll opt for the easiest method to develop in react native which involves using the Expo Go app on your phone regardless of your operating system so on your phone just go to your app store whether it's Google play or App Store and search for Expo go install it and get get ready to scan this QR code if you're on Android you can open up the Expo Go app and then scan it within it and on iOS you can just scan it with your native camera app and on both operating systems make sure that you're connected to the same network also on iOS make sure to go to the expoo settings app and turn on the local network and also turn the VPN status off to not connected this is necessary for the Expo to connect properly so let's give it a go I'm scanning my code and I'm going to press open in Expo go and immediately we're in it says open up your app.js to start working on your app so let's do exactly what it says navigate to our layout and let's modify this to something like Aura our new app and we are live you're developing your first ever react native appli a that's amazing so pat yourself on the back for learning how to set up react native projects with Expo moving ahead we can now create different routes by creating different files in the app folder just like in nextjs first we'll move our code to a special file called index.js so copy everything we have here and create a new file called index. jsx and paste it right here this index file is our homepage or in web terms that would be a forward SL route and the underscore layout will be present in all of the routes so if we were working with web here you would do something like a navbar or a footer so now here let's create a starter template code we can use a special snippet called RN FES it's a reactnative functional expert component with Styles and we can rename it to root layout and if that didn't work for you that must mean that you don't have the es7 plus react reduxx react native Snippets installed so simply install it and give it a go once again the command is RN FES and enter and then you can rename to root layout that makes it much simpler to do right now within here we can also Center our text so let's apply some styles to this view by saying style is equal to style styles. container and then within this Styles sheet. create we can create a new container class we can give it some Styles like display is flex let's also give it a flex off one let's give it a line items equal to Center as well as a justify content equal to Center as well these properties should Center the root layout and you should be able to see it in the center of the screen now to render the index jsx on our home screen we can modify the layout to render different screens and specify the default one or we can just use the slot property from Expo router so let's import it at the top by saying import slot coming from Expo router and then within this root layout we can simply return something known as a slot we don't even need the Styles anymore so now we can save it and you can see Aura coming directly from our index. jsx the slot basically just renders the current child route think of it like children prop in react and this component can be wrapped with other components like this if we were to expand it and then wrap everything in a react fragment like we would do in react and then it allows you to add something like a footer and then we can give it a header and a footer below but as you save it for the first time ever we can see a render error saying that text strings must be rendered within a text component okay that's a helpful error so let's simply render a text component right here and let's wrap header and footer right within it there we go it's hard to see them they're at the top left and at the bottom left of our container later on we can properly style them but what matters most is that they are here this is one way to implement navigation and layouts within react native an alternative route is to use something known as a stack of different screens so we can import stack from Expo router and we can remove this return and instead of that we can return a stack within the stack we can declare each one of our individual screens so here we can say stack that screen which will be a self-closing component with a name equal to index and options equal to Heather shown set to false as we don't need to show the header and there we go now we can see our index screen now say that you want to create a profile route all we have to do is create a new file within the app which will be called profile. jsx run RN FES it's going to say profile but now how do we navigate to it let's return to our index. jsx and add a link component coming from Expo by saying import link from Expo router so right here we have the text we have the status bar and then below it we can render a link which will say something like go to profile and as we would on the web we can give it an H that's going to say something like forward SL profile and a style of color blue it is as easy as that a go to profile button appeared and on your phone you can press go to profile and just like that we got navigated to a second screen how crazy is that just a bit of setup here and there but now we have a complete structure and the knowledge for creating as many screens as we want within all the new react native applications that you create with that in mind both Expo and react native offer plenty of components and elements that I could go on and on about but it would take forever luckily I've got you covered to help you understand the react native better I've created an awesome app that covers all the fundamentals and essential features you need to learn as a beginner so let's start building the app and put everything into practice now that you know how to create your react native and Expo application and Implement a couple of different screens you can navigate between let's add some styling to our application sure we have been styling using stylesheet so far but as we have routing similar to that in nextjs we also have similar styling and that my friends is native wind as the name suggests it uses tailin CSS as a scripton language to create Universal style system for react native so head over to Native wind and you'll see a little Banner saying native wind 4.0 is coming soon for some reason they're jumping from V2 to V4 skipping V3 but no worries as with everything I'm teaching you in JavaScript Mastery what matters the most is reading the docs not necessarily following along exactly with what I do so if the version got updated in the meantime that's totally okay just follow the docs and let's get it installed in this case we're going to go to Quick Start Expo and we don't have to install our Expo app we have already done that rather we can just install native wind so let's copy this command open up our terminal split it and then paste the mpm install native wind once that is done we can also install a Dev dependencies of Tailwind CSS by simply pasting the command mpm install save Dev Tailwind CSS the second step is to set up Tailwind CSS by running the command MPX tailin CSS in nit same as we would do on the web so let's say MPX tailin CSS in nit which will create a new Tailwind CSS config next step we have to do is copy this Tailwind CSS config that has the content added here so that it knows within which files we're going to implement Styles so simply copy this content part right here and replace the existing empty content next we'll have to add the Babel plugin so let's copy the plugins right here go back to application and don't be fooled we don't want to modify these plugins right here within ta. config.js rather we want to modify the plugins within Babel config by simply adding a new plugins array now that's it we can start writing code so we can replace the Styles she sheet with Tailwind CSS like class names let's do that by copying the class names from here closing the existing files and completely removing the Styles and the stylesheet from index. jsx removing the Styles sheet import and instead of styles we can simply render the class name so now if we save it you can see that it jumps to the top the background color also changed it's not white so we can see that the styles are still not getting applied since we modified our Babble config we can open up our terminal and press R to restart the server and we can also go to our Tailwind doc config within the content we can modify our uppercase app folder to lowercase app and it's not only one app file we want to track all the files within the app folder so we can sa slash asterisk asterisk meaning everything within all the folders within it for SL asterisk which means all the files and then dot for the all extensions later on we can also modify this custom directory to say/ components there we go so now if we go back and if we try changing the text to something like class name is equal to text- 3XL you can see that it actually applied all the changes the text 3 Excel as well as all the flex properties belonging to the view this is all already looking much better now that we know that native wind is working let's quickly go back to Tailwind Doc config.js and play a bit with our theme rather set up our colors and fonts so we can build our app successfully throughout the entire process of building our app we'll be referring to our polished figma design as you can see there are a lot of pages which will build we'll have an onboarding screen sign up and signin screens and also our great looking homepage so with that in mind as with many of our videos you can get access to this complete figma file for free by clicking the link down in the description and then you can follow along and build your Tailwind theme setup the way you would go about doing that is you can select a specific screen like we have this one right here and then you can see all the colors that we have for example this 161 622 and copy it then back in the theme you can say extend colors and you can also add primary and you can say hash and paste that color so now every time that you refer to this color you don't have to repeat 161 622 rather you can say text primary we'll also use a couple of other colors and font families within this video so in the read me down below you can copy the final Tailwind config and paste it here as you can see there's basically 10 colors and then we're also mentioning some font families to make our text look better now that we have these fun families we have to manually import all of them so in the description down below you'll also be able to find a complete assets folder so let's remove the existing assets folder download and unzip the one from the description and then simply paste it right here in the root of your directory you'll be able to see that we have a lot of fonts icons images and more and to make her life importing those assets a bit easier I have also created a constants folder which you can find somewhere near the assets you can also download it unzip it and paste it right here if you check it out this will simply import all of the files from the assets and then export them so we can import them in an easier manner with that in mind we have to put those fonts to use so we can go to layout within the layout we'll have to load all of those fonts in that's a bit different from what we do in nextjs but it's not that hard we can use the special Hook by importing it first called use fonts coming from Expo font once we have it we can use it as we would use any typical Hook by saying const fonts loaded is the first parameter and then the error if they don't load correctly is the second one and we can call it by using the used fonts and passing in an object of all of the fonts that we want to use the way it works is you first give it a string where you specify the name of the font such as Poppins black and then you require the link to where that font is saved for example do/ assets SL fonts slash Poppins Das black. ttf and we have to repeat this for every font that we use and you also have to make sure that you spell it correctly the b in the black right here is capitalized so make sure to do it like that and just to save you all the trouble of writing it out and making a couple of typos along the way this complete fonts loaded will be in the read me down below so simply copy it and override it here as you can see we're basically just loading in the fonts now the next thing we can do is introduce a use effect we already know what a use effect is for right it allows us to perform some actions while the page or in this case the screen is loading so let's create a new use effect hook provided a callback function and a dependency array and within that dependency array we can say fonts loaded meaning recall this function whenever fonts loaded change or whenever there's an error and then we can say if there's an error then throw that error and if fonts loaded then we want to call something known as a splash screen and this splash screen is coming from Expo router so let's import it right here splash screen and there's a special method on the splash screen called hide async which looks like this if you hover over it it's going to give you more information it basically hides the native splash screen immediately but before you use it ensure that your app has all the content ready to display when you hide the splash screen or you're going to see a blank screen instead but if our fonts are loaded we should be good to go next if for some reason our fonts haven't loaded yet so if no fonts loaded then we can return null meaning we won't show anything and we can also add and and there's no error so if the fonts haven't loaded and there's no error something must have gotten wrong so we're going to return null and we also have to import use effect from react so if we do that we should be good to go also at the top we can add a special directive also by using a splash screen called Splash screen. prevent autohide async this will prevent the splash screen from Auto hiding before asset loading is complete so now that we have loaded our fonts let's navigate over to our index and let's try to use it within our Aura app we can do that by saying font Dash and automatically you can see how Tailwind CSS intellisense gives us different options that we can choose such as P let's do maybe P black and save it and automatically you can see how our app just gets a lot more character and it will look much much better once we implement this entire phenomenal design and all of the other screens that I prepared for you so now that we know how to spin up a react native application we know how to do routing and we have styles and fonts set up we can actually create the file and folder structure of our application we can do that by first creating a new folder which will be within parentheses and we will call it o like this once again this is the same as within nextjs if you put a folder with within parentheses it's considered a route group allowing you to add additional Pages or screens within it with a special layout So within this o we can also create a newcore layout. jsx file and within it we can run rnf which is a react native functional expert component like this we can rename it to something like oth layout so it makes more sense now what is the reason why we're going toate create a separate layout for the O well if you think about it only the O screens and the onboarding won't have those tabs at the bottom the navigation right if you see all the home screens right here they have the home create profile and so on but our odd screens don't have that which is exactly why we're going to use a separate layout now that we have the layout for our o routes let's go ahead and create them the first o route will be sign in. jsx and we can also run rnf and simply put it right here and rename it to sign in and did I say route I meant screen we're creating screens here so let's create a sign- up. jsx screen as well and run rnfe and rename it to sign up there we go so now our routes for the O are good good and we also have to do a second route group also within parentheses called tabs within tabs we're going to create a new custom layout. jsx where we can run rnfe and rename it to tabs layout soon enough we'll Implement that Bottom bar that allows us to switch between all the pages within the tabs folder and which pages are those or which screens should I say the first one is the bookmark jsx where we can also run rnf and rename it to bookmark with a capital B and keep in mind we're just creating the structure right now to make her life easier later on then we're going to create a create. jsx where we can also run rnfe this will be to create and add videos to our platform we can create a home . jsx and run rnf and finally we can create a profile and finally the profile will also be under the tabs category so we can pull the profile we have created before into the tabs folder finally we'll have one more page which will be within its own folder called search and here we're going to use another concept coming directly from nextjs it's called a dynamic route so let's create a new file and put it within square brackets and call it query. jsx this will allow us to rename the page or get the query information for the specific search our user is trying to do there we can also run rnf and rename it to search great now the majority of our file and folder structure has been set up but we have no way of navigating between those routes so let's go to tabs and tab into the layout here we'll create this bottom part that will allow us then to navigate between all of the other Pages within our app so to see this tabs layout which will create soon we can navigate to our index. jsx and modify this link that navigates the profile and make it go to something like home so we can say go to home and now now if we click on it you can see that now we have the tabs right here tabs folder and the tabs layout which means that we are ready to start creating our tabs so to get started let's import tabs from Expo router by saying import tabs and we'll also use redirect later on from xo- router we can then create just an empty react fragment with which we'll wrap everything and then render the tabs component like so within the tabs component we'll also have a tabs. screen component which will be self-closing and to it we can give a property of name is equal to home and immediately you can see that we have four different things at the bottom home create profile and bookmark and these are the exact files that we have created this is pretty cool right but right now they're just upside down triangles what we can do is of course modify them a bit so I'm going to give it some additional options which is an object that has a title of uppercase home like this we can also choose whether a header is shown on that route so we can say false in this case and we can modify the tab bar icon which will be a callback function inside of which we can destructure the color and the focus State and return the icon that we want to show make sure to use just parenthesis here and not open a function block within here we can return a tab icon which is a new component which we'll create so right here let's say const tab icon is a react functional component that returns returns Well for now we can return just a view view is like a div we'll use it quite often and within that view we can render an image and this image will come directly from react native once again very similar to nextjs if you're used to that this image will accept a source which we can pass into the tab icon functional component so we can D structures of some things like the icon the color the name and the focus state that way we now know what we need to pass so right here below we can render the tab icon self closing and it pass the icon and now we need to import the icons we have created before within our constants so we can say import icons coming from do slash do do slash constants and if we scroll down we can now use the icons. home this is the home icon specifically we also have the Coler coming directly from the Callback function we have the name equal to home and we have the focus state which will simply pass over focused is equal to focused this should give us everything we need to now start rendering our tab icon which needs its image so let's simply render the icon as the source of that image and already you can see a huge home icon at the bottom let's style it a bit by using the resize mode equal to contain this is a bit different but of course we can just read the docks of react native image and understand which props does it accept tint color is another property to which we can pass the color coming from props and the class name using native wind not Tailwind of w-6 and h-6 as well and now we have a beautiful looking home icon at the bottom right below the image we can also render the text and that text will render the name now we can see two different names right here so let's style it a bit by giving it a class name equal to and we want to modify the state depending on whether it's focused or not so I'm going to open a dynamic template string and say if it's focused then apply a font of P semi bold and P stands for Poppins which is the name of the font else apply a font of P regular like this I was almost about to say regular but no it's Poppins regular so then we can do a text- XS right here to make it smaller but now we can see the home two times so we need to modify our options in the Tab screen a bit more and we can do that by modifying the tabs in general so right here we can pass additional screen options equal to an object where we can say tab bar show label will be set to false and now we have only our specific label that we chose also I can see it's not centered properly so let's go into this View and give it a class last name of items D Center justify Das Center and a gap of two to create some space there we go that's better next let's just copy this Tab screen and duplicate it three more times 1 2 3 and that way we can make it work for all of the other icons or screens by changing the name to bookmark changing the title to bookmark with a capital B we can also change the icon to Icon stad bookmark and change the name to bookmark you get the idea right if we save it you're going to get an error because we still have some duplicate screens so before we can see anything we'll have to modify all of them and I do believe that my bookmark was supposed to be a second screen so I'm just going to copy it and move it over to the second place right here after the home so we have home we have bookmark and the third one on our list is going to be create allowing us to add new videos to the platform so name create title create icon. plus and name is going to be create and the last one of our Tab screen will be profile so the name is profile title is profile IC can profile and name is profile if we save it the error is gone we can rigate to the homepage and you can see four of these beautiful tabs at the bottom which if you click on them will navigate to different pages this is great they change the focus State and if you pay close attention at the top you can see that the text within the screen changes this is great so simple and so similar to what we're used to Let's also apply some additional class names to tabs in general by modifying the screen options and giving it a tab bar active tin color which we can put something like let's do hash FFA 001 this one matches our theme a bit more we can also do a tab bar Ina active tint color and we can make it something like hash CD CD e0 we can also modify the tab bar style which is an object where we can change the background color to something like # 161 622 which if you remember is our primary Coler and yes even though it is in the tailin config and we can use it just as a Coler primary where we're here within an object passing to the screen options so we still have to type it out manually just in this case we also can set up the Border top width to something like one I found that to work the best and also border top color to something like hash 232 533 and set the height to something like 84 pixels and now we have this modern looking dark tabs bar but we cannot see the name of our tabs and that's because we have to go to our text and add a special property of style color is set to the color that we're passing from the props in this case that will be white so now you can see this beautiful home bookmark create and so on and we can nicely navigate between them and it's not just about changing the color in the tabs bar it's about actually navigating to different screens of our application which soon enough will look exactly like it looks right now on figma this is a beautiful onboarding design and I think I like this onboarding screen the most it is visually the most pleasing so let's get started with that as it's our first screen anyway and of course this screen just looks good doesn't yet Implement any functionality but as you know you're building a full stack application so after we're done with creating the onboarding screen after you kind of feel a bit more comfortable working within a react native mobile native environment you'll be able to dive into the sign up and signin screens where will immediately start implementing the logic so let's get started with the onboarding screen you can see our designer here has pulled out specific assets that we can use within the application I have already provided these to you within the assets but in case you're wondering how we can use them and how we can download them yourself you can just select them and then scroll down and click export that way you'll have those assets also you can see that our great designer has also provided us with different colors to implement the gradient looking button with that said let's start working on our onboarding screen which is our index. jsx and you can navigate to it on your phone by simply clicking the index on top left or this is crazy you can use your devices native capabilities like on iOS you can swipe from the left side of the screen and that will also perform the same action that's crazy I mean the power you get with developing in react native is so good because you can develop native mobile applications with Native functionalities for both Android and iOS while writing code that looks and feels like react and nextjs I think you can see my enthusiasm and I hope you share it with me while you're learning how to develop react native applications with that said let's not use the view right here rather let's use something that you learned about in the crash course part of this course and that is safe area view whenever you have kind of the most outside view that should be a safe area view because it ensures that our content is visible on all different devices and of course we have to import it at the top by saying import safe area View and it's going to come from a package react-native Das safe area context like this it will simply ensure that our content doesn't overlap with a status bar a bottom bar or anything like that both on iOS Android and all other types of devices let's give it a class name equal to BG primary and h- full for full height and that will immediately turn our device black next we can wrap everything within the safe area view we're going to also render a scroll view this is coming directly from react native and we can give it a Content container style equal to height of 100% so the whole screen should be scrollable the reason why we implement this is because the height of our content might be larger than what some smaller devices support so they might need to be able to scroll up and down to see it fully now that we have the scroll view we can implement the view within it like a div and give it some class names such as w-o for full width justify d center items D Center age- full for full height and padding X of four for some padding horizontal this is just to Center everything in the middle of the screen next we can render an image also coming from react native we already know what kind of properties does it have like Source equal to and we once again have to import the images at the top by saying import images from slash constants and we can now use the images. logo and of course you have to spell constants properly there we go Aura at the top this looks great let's also give it a class name equal to w-130 pixels and h- 84 pixels which makes it look bad but we can give it a resize mode equal to contain which will contain it within those width and height essentially making it a bit smaller right below this image will render a second image which will also be self-closing with a source equal to images. cards it will have a class name equal to Max dw- 380 pixels w- full and h- about 300 pixels also let me fix this typo right here and don't forget we also have to give it a resize mode equal to contain if we save it this is looking much closer to what we have on the final design but of course now is the time that we add a couple of text elements and the button so let's create a view for that still within the same view below the image we can create a new view with a class name equal to relative margin top of five and give it our first text element with a class name equal to text- 3XL to make it very big text- white and font Das bold as well as text- Center to center it in the middle of the screen here we can say something like discover endless possibilities with and then within it we can render another piece of text it's like having a span within a P tag that will say Aura which is our app name and we can give it a special class name of text- secondary -200 and this is the first time we're using one of our special theme colors we have added within our Tailwind config there we go that's looking good let's also create a space right here to divide Aura from width that's looking much better and you see how this Aura in the design has this special underline well let's add that moving below both of the texts we can create a new image which will have a source equal to images. paath with a class name equal to W d136 pixels I found that value to work the best and h-15 pixels for the height we're going to also make it absolute as we need to absolutely position it below that aura text and give it a minus bottom-2 and minus right -8 to position it just right let's also give it a resize mode equal to contain there we go that's much better now we can go below the image and below the view and render another piece of text that will say something like where creativity meets Innovation and no this was not created by Chad GPT I thought of this myself for sure embark on a journey of Limitless Exploration with aura I mean who wouldn't use the app once you read this text let's give it some class name such as text- smm font dular which is p regular text- gr-100 so we can actually see it margin top of seven to divide it a bit from the top and text- Center to center it vertically this is looking great and finally let's create our first custom component of the day which is going to be our button so to do that we go to our file explorer and create a new folder called components within components we can create a new file called custom button. jsx and there we can run rnf to quickly spin up our custom button and now that we have our custom button we can go back to our index. jsx right below the text we can start typing custom button and automatically imported from components if we save it you won't be able to see anything that's because it's showing dark text on dark background but this is our sign to dive into the custom button and start implementing it first things first it's not technically a button it's something known as a touchable opacity as we have learned before but now you get a chance to put your skills to the test to actually use what you learned in a real app so let's import the touchable opacity coming from react native and instead of wrapping everything with a view let's wrap it with a touchable opacity component and don't forget to import the text we'll still need it we still cannot see anything so let's give it some classes I'm going to say class name is equal to and I'm going to make it a dynamic template string of BG secondary there we go that's already better at least we can see something we can make it a rounded - excl which will round the corners and give it a Min dash of 62 pixels for the height we can also make it justify Center and items Center and this is already looking a bit better let's style the text element within it by giving it a class name equal to text- primary font Das P semi bold text- LG to make it a bit larger and within it we can render whatever we want to say so what we can do is pass some special props to a custom button to truly make it a custom reusable component we can pass some props like the title because every time we use this custom button we don't want it to say custom button we want it to say something like continue with email in this case we can also pass a handle press not handle click handle press in this case which will be a callback function for now we can leave it empty and we can also pass container Styles which are some additional Styles we can pass such as W full and margin top of seven so if we go back let's put all of these props to use by first destructuring them we can destructure the title the handle press the container styles and in some cases we might also have text Styles as well as is loading property we'll have it when submitting the video so now we can expand our touchable opacity and we can also give it the on press Handler which will be equal to handle press which we're passing as a prop we can also modify the active opacity to something like 0.7 I think looks best this is the opacity of the button once you press it and we can apply the container Styles right within our other styles which will make it fit the full width of the screen and if is loading we can apply the opacity of 50 to make it seem like you cannot click it that's going to look something like this and also we can give it a disabled state if we're loading which is not happening right now so it looks good next let's also make this Dynamic template string the class names for the text element which is going to look something like this if we properly close it and we can also use the text Styles right here if we're passing any and most importantly we can make this text render the title which is coming dynamically from the index page where we're calling this custom component and there we have it we have our button the last thing we need below the scroll view will be a compon component called status bar it's a self-closing component which we can import from Expo status bar right at the top and it will have a background color of # 161 622 and a style of light do you see what happened when I added that let me comment it out and bring it back basically since our app is in dark mode it also darkened status bar and gave it a style of light so now you can see your battery percentage clock and all the other stuff at the top as well this is very useful in case you want to show it or hide it within your application one thing that I've noticed recently is that some apps purposefully show it because they want you to have all that information but some apps sneakily hide it so you get lost in time and spend more time on the app I noticed that Tik Tok actually hides all the information and shows you just the videos so you lose the sense of time and you keep scrolling but now you see the other side of that and you learn how to implement it so that potentially you can trap your users within the app or you can be good in them and give them all the information they need in this case we'll be the good guys with that in mind the last thing we need to do to finalize our onboarding is actually provide our users with a way to exit it meaning to go to the next screen so for the first time we're going to use the router right at the top coming from Expo router we can import two things the redirect component as well as the router itself in this case we don't have to declare it as a hook rather the only thing we have to say is router. push and we're pushing to forward slash sign- in as does the next compon component we want to work on and believe it or not that's it for our onboarding screen now there's just one small thing I noticed and that is that back here in our view instead of H full we can give it h-h and then about 85 VH this will actually help us Center the content in the middle of the screen and we can even make it Min Dash so this is going to be the Min height of the screen and now it's nicely centered with that done I want you to take your phone in your hand and admire what you have done like you can even move your thumb up and down and you'll see it will nicely scroll you can kind of hover over the button to see how the touchable opacity changes and you get all of the powers of developing native mobile application with a code that let's be honest feels like you're writing a web app with that in mind this looks great to me let's just continue with our email and let's start implementing our off layout and then both of our signin and sign up screens phenomenal work so far let's close all of the currently open files and navigate over to app o and then the layout here within the layout we can return just an empty react fragment and we can then render a stack of course this stack has to be imported from Expo router so let's get stack coming from Expo router and you know that we first wrap everything in a stack and then within it we can render multiple stack. screens which are self-closing components the first one in this case being the one with the name equal to sign in and it will also have options equal to header shown which will be set to false and we can also just duplicate this entire screen stack right below and just change the name to sign up there we go so now we have the signin screen which we're on and we can also show that same status bar that we rendered not that long ago right here by saying status bar coming from react native and it will have a background color of # 161 622 and a style equal to light and don't forget there are two types of status bars in this case we don't want to use the one coming from react native rather we want to import the one coming from Expo status bar and now that we have our layout we can dive right into the sign in screen right within here we can wrap everything in a safe area view which is coming from react native safe area context right here we can give it a class name equal to BG primary and H full for full height and now we have a dark screen within it we can show a scroll view so we can scroll through it and then have a regular view as well of course the scroll view has to be imported from react native and we'll have to navigate back to our signin every time let's also give this view a class name w-o justify Das Center h- full padding X of four and margin y of 6 and remember that last thing that we had we didn't want to do H full rather we've done m-h 85 VH because this will actually Center it now let's not forget to import images as we'll use them right now by saying import images from slash do SL constants and we can start using our first image right here by using a self-closing image tag which we need to import from react native and give it a source equal to images. logo with a reiz mode equal to contain and we can also give it a class name equal to w-5 pixels and h- about 35 pixels there we go below this image let's also render a text element that will say something like log into Aura like this and we can also give it a class name equal to text- 2XL to make it a bit larger text- white text- semi bold margin top of 10 and font d p semi bold and this does seem to be a bit too much down on the screen so I'm might want to return this to h-f to see how that will look like yeah I think this is better for now we can easily change later on now we're going to dive into creating a second custom component of the day and it's going to be a very important one it's going to be a custom form field or an input so let's go to components and create a new form field. jsx component where we can run RN Fe to create a basic form field component and we're going to start by giving this view a class name equal to space- y-2 which will create some spacing between the elements right within it we can also have a text element that will simply say what kind of a form field this is so let's give it a class name equal to text-base text- D gray -100 and font DP medium and now we can go back to sign in and we can render our first form field coming from components form field you can see it right here at least it's label to this form field we can pass a couple of different props so let's immediately expanded and let's give it a prop of title which will be email a value which needs to correspond to an actual form value so while we're here why do you say that we immediately create a new use State field by saying use State snippet we can call it something like form and set form at the start equal to an object with an email property of an empty string and a password property as well of an empty string so now we can set the value of this form field to be form. email as simple as that next we need to also pass the handle change text so we know how we can modify it and this will be a callback function that accepts the event and calls the set form Setter where we destructure the existing form values and then modify the email to be equal to the event that we're passing we can also pass some additional Styles like other styles to this such as margin top of seven and we can also pass the keyboard type which in this case will be email address and in the other case it can be a password this is useful for autofilling information such as emails names and so on now we can also duplicate this right below and modify it to match what we need for a password so the title will be password the value will be formed at password and here we can modify the password property and we don't need the keyboard type and of course don't forget to import use state from react once we do that we can go back to our screen and we can see two different form Fields so let's get back into the form field and let's accept all of these props things such as a title value sometimes we might also want to have a placeholder handle change text and other styles and we can also spread out all of the other props that we might have here as well and now we can use them first of all we can add the other styles right here to our view in case we want to further modify the styles for each specific element so we can simply render the other styles here this will space them out as you can see on the screen then instead of saying form field we can render the actual title that will look something like this email password and finally we can start creating the view for the text input by saying View and we can give it a class name equal to w-o h-16 padding X off 4 BG black 100 and I know you can barely see it so just so it's easier to see at the start I'm going to add something like a border of two and border of red 500 that way you can see what we're working on after BG black I'm also going to give it a rounded Dash 2XL so it's going to be a bit more rounded on Focus I'm going to give it a border Das secondary so later on once you tap it it will turn orange and we can also give it items Dash center now that you know what we're working on on I can change this border from Red 500 to Black 200 that will be a bit less in your face that's good right within it we can render a text input element which we can import from react native it's going to be a self-closing property and to it we can pass a class name equal to flex one text- white font Dash p semi bold and text- base we can pass it the value equal to value a placeholder equal to placeholder a placeholder text Coler equal to # 7B 7B 8B an onchange text property equal to handle change text and then we can have a special property off secure text entry so if it is a password then we want to hide what you're typing so what we can do is create a new use State field called show password use State snippet show password set show password at the start set to false and then secure text entry can be equal to if title is triple equal to password and if not show password then it will be hidden it will be secure text entry else we will show it and of course we also have to import use state if you go back here that looks good and now if you tap somewhere in the middle of the input I think you should be able to trigger your keyboard right here as you can see it on my screen similar for the password we're going to improve these inputs later on on but you should be able to trigger it by pressing it in the middle next let's Implement that feature to show or hide the password so right here below the input we can say if title is triple equal to password then show The Following thing a touchable opacity we learned what that is that is basically a button and on press it will call a call back function where it will set show password to be the previous value of show password so basically it will toggle it on or off and we can also render a self-closing image right here coming from react native so we have to import some images from the top by saying import images from do SL constants and then we can give it a source equal to if not show password then it's going to be icons. I else it will be icons. iide and I noticed that I should have imported icons not images there we go coming from constants so now we can see this huge I in the middle let's also style it a bit by giving it a class name of w-6 and h-6 and a resize mode equal to contain okay but it's kind of still somewhere in the middle there so definitely something's wrong with our classes I think I need to make this view a flex row like this that's going to put the I at the end and now you can trigger both of these inputs but if you start typing at the second one like ASD you can now show or hide it this works perfectly so with that in mind you now have a great looking or screen you can also go back and we have our inputs so let's exit the form field and let's finalize the login screen we can do that by bringing back our button component by calling a custom button self closing and we have to import it at the top so we can say something like import custom button coming from do do slash do slash components forward slash form field and I notice that I don't have to make it curly brace it has to be imported like this as it's the only default export so now that we have this button let's pass it some props like a title equal to sign in let's pass it a handle press equal to well this is a very important function here we will actually submit our form form so we can create a new function cons submit is equal to an arrow function that looks like this and then we can call that submit right here on the handle press let's also pass it container styles of margin top of seven to divide it a bit and then since this action will take some time we can also create a loading state right at the top the loading State we can create by saying use State snippet and I'm going to call it is submitting set is submitting and the start set to false and then we can simply say is loading will be equal to is submitting there we go but why is this button acting like an input looks like I have done a wrong import the custom button should be coming from the custom button file there we go that's much better and also below this button we can add a couple of pieces of text something like view that will wrap those texts with a class name equal to justify Das Center padding top of five Flex of row and gap of two and then it will have two children elements the first one will be a text that will say don't have an account I mean seriously and it will have a class name equal to text - LG text- gr-100 and font DP regular there we go what happens if you don't have an account well let's render a link component which we of course have to import from Expo router by saying import link from Expo router and now we can just make it say something like let's do sign up and of course every link needs an hru so we can make this one point to sign Dash up and give it a class name equal to text- LG font DP semibold and text- secondary so we can actually see it there we go don't have an account sign up and this now actually points to the signup screen that is great let's also remove this ugly top bar which says index and O and doesn't work with our Dark theme at all we also have to modify the layout for the entire route group so let's duplicate this layout right here name it in parentheses o and then we simply say header shown false so now it hides it as well and we see this beautiful bar at the top and the content slides just a bit we do want to center it which we'll do soon but at least now we have a full dark mode Let's also repeat this for tabs and we can also repeat it for for SL search slash query like this so now we're hiding the search bar everywhere we do get a warning here so for now I will simply comment this one out and we're going to implement it later with that said let's go back to sign in and now that we have hidden it now it might make sense to turn this from H full to Min Dash - 85 VH as that's going to push it down a bit I think this is approximately centered but of course you can play around with it and modify it as you like great with that said our login screen has now been implemented we can actually type stuff in and we can also type the password and even show and hide it that's great the sign in doesn't do anything as we didn't yet submit it but we do have the sign up screen right here which for now is completely empty so what do you say that for the sign up screen we simply copy everything we have right here in the sign in and simply paste it within the sign up of course you have to modify the export sign up and also the name of the component right here to sign up and now it seems like a sign in but with only a few modifications we're going to immediately make it a sign up those modifications include adding a username right here at the top as when you're registering we also have to know your username then instead of login we're going to say something like sign up to Aura and we're going to duplicate the email field to add new one on top of it this time we will say something like username form that username here we'll change the username text and add a bit of a larger margin top of 10 and also remove the keyboard type as it's not an email and with that said we have a beautiful sign up screen besides one small tweak right at the bottom instead of don't have an account we can say something like have an account already well what you're waiting for right go ahead and sign in and modify the hre to sign in so now we have beautiful navigation from sign up to sign in and we can go back and forth from onboarding sign in sign up and more you my friend have successfully completed the first three screens of your react native application with that in mind I think you're ready to start adding some logic to our app let's make these signin and sign up screens not be just pretty canvases let's make them actually do the work so we can sign our users up to the application and believe it or not your first react native application will also be a full stack application we'll be using aight to add o databases functions and storage to your application so that way you will be able to have users which can then upload videos to your platform how cool is that so if you haven't done that at the start click the link down in the description so you can follow along with the video and what I'm doing sign up or sign in and then go to the console finally we can start adding logic to our react native application starting with authentication first things first let's create a new project let's name it something like JSM uncore and then you can either put your app name or something like react native crash course I'll use that one and I'll let you guys choose the names I'll click next and here you can choose a deployment region for your project project I'll choose the first one since I'm based in Europe but you can choose something else as well based on your location and I'm going to click create there we go our react native crash course project has been created so we are greeted with this nice getting started guide right now you can choose between Apple or Android either one is okay but soon enough aight will add another thing such as Expo signifying that it's crossplatform in this case I'll proceed with with apple we can choose our app name I'm going to type Aura under bundle ID you can use whatever you prefer we can follow their example and then do something like comm. JSM do and then the app name so I'm going to say comm. JSM do Ora in your case you'll most likely have to choose a different name which is totally okay but what's important is that whatever you choose here copy it write it down somewhere because we'll need to use it later on with that that said click next and click skip optional steps the steps are the same for Android devices as well you can skip the optional steps and then you'll be redirected to your dashboard let's quickly go back to our code and go to app. Json here if you scroll down under iOS or under Android whatever operating system you want to work on you can add a new property called package make sure to put it within double quoted strings and type out exactly what you typed out as your bundle ID in my case it was comm. jm. or and that's it you can put it under iOS or Android depending on what you want to do next let's copy the project ID right here from the dashboard and then create a new folder in the root of our directory called lib as in library and within it create a new file called app .js within here we can create and Export a new aight config object which will look something like this the first thing we can add will be the endpoint so we can say endpoint is equal to https col cloud. aight. slv1 this is their hosted version of the platform but ight is completely open source and allows self-hosting as well so in case you want to do that you can in this case we'll proceed with their Cloud version the second thing we can add is the platform and here you can type the bundle ID that you chose before in my case that's going to be comm. JSM doora the next thing is the project ID which is the one that you just copied from your dashboard next next let's check out o here we can create users manually but rather than creating users manually we'll connect this to our application and then created using our great signin and signup forms we created not that long ago there are multiple options for doing authentication here we have phone magic URLs Anonymous jwt's and a lot of o o providers basically anything you can imagine in this case we'll simply be using us email and password next let's look into databases here we can create our own database so let's do that by choosing a name I'm going to do something like JSM Ora and click create it has been created and we've been given the ID of the database so let's copy it and back right here we can say database ID and we can paste that ID we just copied next let's create our first collection it'll be for our users we can call it users and click create we also get an ID of the collection so let's copy it and let's paste it right below that's going to be user collection ID and we can paste the ID right below next we can go back to all collections and create a second and last collection we'll have for this application which is going to be called videos and we can click create and we can copy the ID and paste it below by saying Video Collection ID first let's go back to the users collection and add the attributes our users need so let's create our first attribute it'll be of a type string the attribute key is username size is something like 2200 just so we have enough space but of course you can go much smaller as usernames are typically that long we can make it required and we can click create let's go for another one it's going to be of a type email which you can get right here its name will also be email and it will be required next one will be of a type URL and it will be called Avatar and it will also be required finally we can have a string off a type account ID with a size of about 2200 just so we don't hit the link liit and also required and then we can head over to settings scroll down and add a new roll under permissions we're going to add any and turn on all cred operations that way all users can perform all cred operations now let's modify the attributes for our videos collection go to attributes and create our first attribute of a type string with the attribute key of title 2200 100 as the size and make it required the second attribute will be of a type URL and its attribute key will be thumbnail it will also be required the third one will also be of a type string and it will be the prompt that you use to create that video this is a special feature of our application where people can type in the prompt that they use to generate that video as you can think of of it as a social platform for sharing AI generated videos and we're going to make this a bit longer like 5,000 characters and make it required next we need the actual video so that will be a URL type with the attribute key of video and it will be required and finally we need a very important attribute of a type relationship so we need to create a oneway relationship with a related collection of users the relation will be many to one which basically means that one user or one let's call it a Creator right here under the attribute key can create many videos and we can also see that right here videos can contain one Creator and then Creator can belong to many videos on deleting a document we can set document to null and click create finally we can go to settings and also enable permissions we'll give permissions to all users and we're going to give it all cred operations and click update great so now we have successfully created our app right project o is set up by default we have set up the database right here with two different collections that now have their own attributes and finally we can move on to creating storage so let's create a bucket let's give it a bucket name of something like files and click create as before we can immediately copy the ID of the bucket and we can add it right here at the bottom by saying storage ID is equal to the ID that we just copied finally we can go under settings permissions and we can make all of our users do anything they want by giving them all the permissions and if you click update you'll get a quick alert saying that the maximum file size you're trying to set is above the limit so scrolling down we can change this over to 50 megabytes which is allowed within the free plan that way you can update this first and it make it just 50 megabytes that's good and now we can also add a second roll of all guests and give guests only read permissions and click update so now the locked in users have full permissions and guests have only read permissions and we have also set up our maximum file size now let's also allow for specific extensions jpeg PNG gif or GIF and MP4 and click update that's it our bucket permissions and settings have been updated all the IDS and all the information that we need to hook up to our aight Cloud are now here and we are ready to start connecting to our aight client which will allow us to create users upload videos make relations between them and upload files to our storage exciting stuff ahead so let's get started with setting up our app right within the code so we can focus on what we wanted to do not that long ago and that is Implement Logic for our complete authentication now aite provides a couple of SDK libraries for major programming languages and Platforms in this case we'll be using a client library for react native s Decay it's currently in beta but I went ahead and tested it thoroughly and everything was working properly so it's safe to use let's go to the GitHub page of that SDK the link for that will be in the description and while we're here we can also give it a star we can share some love for this developer creating the mobile SDK as they don't have a lot of stars right now has it currently in beta and we can scroll down to go under installation we can copy this command and within our terminal we can paste it right here this will install react native app ride and react native URL pills which I guess they need to make this work after that is done we need to initialize our SDK so let's copy this block of code and paste it just below we are importing the client let's do that all the way at the top from react native aite then we initialize our react native SDK and we set up our endpoint project and platform this is easy to do as we have this object with all the information so we can remove this fake stuff right here and simply say ight config do endpoint or we can even shorten it at the top and say something like config and then config right here. endpoint which is our endpoint then we have our project ID which is config do project ID and finally we have a config do Platform it's great that we collected all that information beforehand so now it's just easy to set our client up once that is done we can make our first request so let's copy the code for it and paste it right below let's indent this properly and as you can see we have a function that tries to register a user we're simply calling account. create we create a new unique ID with an example email password and name and then we call a that then function which simply conss the response so now we can call this somewhere within our code to do that let's first turn it into a function const create user is equal to a callback function and we can put this code right within it let's just move it a bit up there we go we have our account create and we can also add export right here before so we can use this function later on and let's not forget to import account coming from react native ight that's right at the top because we need to initialize our account instance and then set it to the account variable right here then let's go to our sign up since that's the page that that I currently have opened so we can test our example function call I'm going to go to app o sign up and then we're calling this submit on click so here we can call create user and unfortunately it doesn't Auto Import it for me so we can do that by saying import create user from that sl. lib slaight and once we call the submit we call the create user Let's test it now back within our application let's open up up the terminal and press R to reload and I can see an error here saying that the prop ID doesn't exist I think that's going to be right within our app Rite so let's navigate and you can see here ID unique we can import that ID from react native aight now that we have that let's once again open up the terminal click continue with email navigate to sign up and then click the sign in button this should trigger the upright account creation it says project with the requested ID could not be found please check the value of x ight project header to ensure the project correct ID is being used so let's make sure that the project ID indeed is correct by going over to aite and then referring to our project ID here looks good but here set project the ID should be uppercased there we go now it's pointing to the right thing so if we save it and click sign in one more time you can see something that looks like a piece of data which would make me assume that the account was indeed created successfully so back within our dashboard let's go to O and there we go we have Jane Doe with the me add example.com email and that's the only thing we care about that means that we have successfully created created a user from within our application for now I think we can safely delete Jane as she wasn't a real user with the data that we typed in and we can focus on hooking up our inputs to our form and then creating a new user but for real this time so back within our code let's go back to aite where we'll create all of the functions like creating a new user signing in a user getting the user information and more starting off of course with creating a user so we can scroll down to where we have this create user function and let's remove everything from here and start from scratch just so it makes complete sense we'll first open up a try and catch Block in the catch we can consol Lo the error that we got just so we know what's happening and we can also throw a new error by saying throw new error and then we can pass the error in in the try we can try to create a new account by saying const new account is equal to await account. create and we have to pass a couple of things to it first we have to pass the user ID and you can see that right here in the docs create user ID of type string then email then password and then name you also get more information about what exactly this this endpoint does so first we're going to use the ID unique to pass a new ID and then we have to get the information about our current user which will pass through params so the first parameter will be email then password and then username so just like that right here we can set the email then the password and then the username since we are waiting we also have to make our function Ace think then if we don't get a new account we'll also throw a new error like this else if the account has been created successfully we can try to create a new profile picture by saying const Avatar URL is equal to avatars which we need to create right here where we have the account by saying const avatars is equal to new avatars coming from react native aite and to it we pass the client so now we can say avatars doget initials this is a special function which basically as it says if you hover over it gets the initials of the user's name and then uploads that so you get the special URL so you can pass the username right in then we can await and call another function which we can create which is sign in so let's say sign in and let's create that function function right below export async function sign in that accepts an email and password that's going to look something like this within it we can open up a new try and catch Block in the catch we can throw a new error and pass the error right in but in the try we can try to establish a new user session by saying cons session is equal to await account. create email session and this is a method given to us by aite to allow the user to log into their account by providing a valid email and password combination so let's pass in the email and password great and finally once we have the session we can simply return it now we can call this sign in function right above and to it we can pass the email and password which will will pass into the create account or create user rather once we sign in we can create that new user in the database by saying const new user is equal to a wait and as we have created an account instance we have to create an instance of databases so right at the top we can say const databases is equal to new databases coming from react native aite to which we can pass the client and right below we can say await databases. create document like this to it we need to pass a couple of things the database ID The Collection ID the document ID and then the data so let's do it one by one we have the database ID stored under config database ID we have the collection ID stored under config do user collection ID then the ID of the document since it's new we don't have it already we can create a new unique ID by saying ID unique and then we need to pass the object with all the information about the user such as the account ID which will be equal to new account do dollar sign ID email which we get from the form username which we get from the form and then Avatar which will be equal to Avatar URL that way we create a new instance of the user in the database and at the end we can simply return that new user perfect now our function for creating a new user has been completed as well as the function for signing in and we can can call it within this submit function once we click sign in or now that I look at it the button should say sign up so let's fix it and make it say sign up but of course since now this is a real function we have to pass real data to it so let's first check if we actually have that data if no form. username or no form. email or or no form. password if either one of these is empty then we want to issue an alert and with react native it's easy to do an alert you simply say alert import it from react native and then say alert. alert of type error or rather this is the title and then you pass the message please fill in all the fields if we do have all the fields we can set is submitting to be true and then we can open up a new try and catch Block in the catch we can do an alert. alert that's going to say error and we can render the error. message we can add a finally clause which will set submitting or set is submitting to false because either way if we got an error or if it succeeded the loading is done and then in the try we'll say const result is equal to await create user and since we're using a weight we have to make this function a sync and we have to pass three things to this user function one by one email password and username so let's do just that form. email form. password and finally for form. username and once we get the result we'll later on set it to Global State using context for now let's leave it as it is and let's simply use the router function coming from Expo router and replace the route by pointing to forward slome so let's give it a shot and let's try to sign up I'll start typing my username like JS mastery I'll do an email of contact at JS mastery. proo and I'll choose a password something like 1 two3 two3 two3 there we go we can also check it it looks good so let's click sign up and we got redirected back to the homepage I won't save it yet which means that it succeeded because we reached the end of the tri block that that is great but what happens now if I go back to profile or if I try to go back and then again continue with email once again we are back to the login screen which is a good thing right because we haven't yet implemented the submit function off the sign in screen so let's copy this entire submit logic that we have here move over to sign in and replace this submit this one will be very similar we set is submitting we're doing everything the same but instead of creating a new user and getting the result we simply want to call await sign in and this sign in should be coming from the aight file so we can say import sign in coming from SL SL lib app right and then we're saying await sign in the sign in accepts only two params email and password so we don't have to pass the username as we already know who we are and then also after we log in we want to set it to the global State and point to home so now let's verify whether we have successfully created our account I'm going to type in the same email I had typed before contact JS mastery. proo and 1 two 3 1 two 3 1 two3 and sign in in this case we have an error possible unhandled rejection coming from the fact that we don't have a username okay that's my bad I should have removed this no username because here we don't even have the username field so if we save it we can type in our password one more time and we can sign in this time we get a different error saying that I forgot to import the alert coming from react native let's see if we have the router there we go I got that just to be safe I think I have everything right now so if I give it a go we indeed got redirected to our homepage which means that we're successfully signed in and that's great and all but what is it good for if I just close the app like go right here and reload and then the next time we have to log in again and go through the onboarding screen we don't want to do that we have already seen what the app is about and we have already created an account so the next thing we'll do is we will Implement a global context state that will remember when our user has logged in and automatically redirect them to the homepage first we have to create a new folder within the root over directory called context and within it we'll create a new file called Global provider. JS as it will Prov provide us with all the state that we need so let's first import create context use context as well as use State and use effect coming from react then we can declare the context by saying const Global context is equal to create context and we can also export con a new hook will create called use Global context which is basically a callback function that simply calls the use context hook and specifies which context we want to get in this case it's the global context but someone or something has to provide that context so let's say const Global provider is equal to and typically this is just a react component that gets children as a prop and it returns a global context. provider like this within it we have children so we can wrap everything but still display all the screens properly next we can choose which types of values we want to provide to our provider so we can see value is equal to an object and here we can declare whatever we want our entire app to have access to so let's create some states first use State snippet will be called is logged in like this and at the start it will be set to false then we'll also create a new used State snippet called user set user at the start set to null and make sure to properly capitalize this U right here and finally we'll create a last state called is loading set is loading at the start set to true because we're first loading that user in then let's create a use effect something like this with a callback function and it will only happen at the start the dependency array is empty here we want to call a special function which will create within aite so let's go to the aight file and create a new function by saying either export async function or you can declare it as a regular export const and we can call it get current user which is equal to an async function like this we can have a try and catch block right there in the catch we'll simply conso log the error and in the try we'll say const current account or currently logged in user is equal to a wait account doget if there is no current account like this we want to throw an error and if we do have a current account then we want to get that user from the database by saying const current user is equal to await databases. list documents first things first you want to say from which database you want to get the documents from so that's config do database ID then from which collection that's config do user collection ID and then you can specify the query meaning how you want to get it and in aite you do that using their own query object which you import from react native app right and it has different methods such as apply bind call we're going to use equal so we want to ensure that the query. equal account ID is equal to the Curve current account. dollar sign ID this way we can get the exact user that's currently logged in finally if there is no current user not current account this time we're looking for current user then we once again throw an error and finally if everything is good and if we have our user we can return current user. documents Z because we only need one user let's also turn this function into an es6 function by saying export const that's going to be an arrow function like this doesn't make a difference but it's good to stick with what you do there we go and now we have this get current user function and we can import it right here within Global Provider by saying import get current user from slash or /li SL upright this get current user is an async function so we can call do then on it first we get a response and if a response exists then we want to set is logged in to be true and we want a set user to be equal to rest as in response else if we don't have a response we're going to set is logged in to false and we're going to set the user to null then we can also catch it meaning if something goes wrong in that case we're going to get an error and we can simply console. log the error and finally meaning no matter what happens if we succeed or if we fail we can have a callback function that sets his loading to be equal to false because we have done doing whatever we're supposed to do now that this function gets the current user information we set it to the state let's provide our entire application with the value of that state with information like is logged in set is logged in user set user and is loading and of course for this provider to do its purpose it has to actually wrap every single screen within our application and the best way to wrap all the screens is just to use it within our main layout right here so we have the stack we can just say Global provider wrap it properly and that way all the screens will have access to the data within the values let's just properly indent it and let's import it at the top by saying import Global provider provider coming from that/ Context SLG Global provider now it does look like there's a problem and I think I know why if we go back to Global provider we never exported it it's never being used so at the bottom we have to say export default Global provider and now we should be good looks like I forgot to put an opening call right here we're calling this as a function so if we fix it we're good and what this does is if we have logged in before it will give us access to the current user and then we can use it within our own boarding to figure out whether we should automatically redirect the user to the homepage so we can head to the onboarding component which is the index of our app and then right at the top we can say const is loading and is logged in which is equal to use Global context which of course we have to import by saying import use Global context coming from Context Global provider and now if we're not loading and if we are logged in in that case we can return a redirect component with an hre off slash home this is how that works and you can see that worked perfectly and if that didn't immediately work for you no worries we'll just do a quick fix make your registration submit form look like this feel free to pause the video and your signin submit form look like this after that give it another go this should save your user to the context now we cannot go back we're tied to home and even if we reload our application right here you see that we automatically get redirected to the homepage if we are already logged in back on upright if you reload your o you can also see that we have contact at JS Mastery Pro with the JSM username right here which means that we indeed have successfully created an account logged into that account within our app and also stored it within Global context so that every time that we launch our app we are automatically logged in that is great and now we are on our home component within the tabs and now I think you can barely see it at the top left but it says home right there which means that we are ready to start working on the home screen and that should look something like this we have welcome back JS Mastery so we know we're properly logged in and we're going to pull our username from that Global context we created then we're going to reuse our input for the search we're going to show some trending videos and we'll have another display for all of the videos that people upload so once again amazing job for coming this far into the video learning how to create react native apps learning how to do file based routing within react native learning how to use Tailwind or should I say native wind within our app importing all of the assets crafting three beautiful screens with react native components and implementing aight for our user management databases and storage more on that later so let's get to the good stuff and let's Implement our homepage to get started working on the homepage we can wrap everything in a safe area view similar to what we have done so far and this safe area view will come from react native safe area context right within it for the first time we'll use a component known as a flat list coming directly from react native it is a self-closing component to which you can pass a lot of props and it is used to render a list of elements we mentioned it in the crash course at the beginning but now we're going to put it to use there are a couple of things that flat list needs such as data which is the most important part and this is an array or array like list of items to render so we definitely need to provide some kind of an array then we need a key extractor so this will be a way for us to get the key out of that item so for example if you have an array of objects where the ID is a number like this you would create a callback function where you get each individual item item and then you get the item. ID out of it in our case later on once we fetch data from aite it's going to be dollar sign ID so let's leave it like that and then most importantly you need a render item which looks like this and this explains react native how we want to render each item in the list so we can open it up as a callback function that's going to look something like this and we can have an immediate return so just parentheses right here right within here we can destructure the data from each item and then for each one we can return something like let's do a text for now and the text can render the item itself or in this case it can be item. ID so let's save it and see what do we have you can see one on top left we can make it a bit bigger by giving it a class name equal to text- 3XL and you can see number one now if we add multiple objects within this array I can duplicate this and add maybe two more we can give them IDs of two and three you can see that it basically creates a list where it shows different text elements soon enough we'll fill this data with the real video data coming from aight for now let me show you another property belonging to the flat list it is the list header component which also is a callback function with an immediate return where we can return a view this view will have a class name equal to margin y of 6 padding X of four and space y of 6 between the elements right within it we want to have another view and this view will have a class name equal to justify between items start Flex row and margin bottom of six and within it we can have one more last View and within it we can have a text element that will say welcome back and right below we can create another text element where we can for now hardc code JS Mastery later on we can use the real username here and you can see this appear at the top as the header to our flat list let's style these text elements let's do the first one first by giving get a class name equal to font DP medium text DSM and text- gr-100 the second one will have a class name equal to text- toxel font DP semi bold and text- white of course it's hard to see it right now because our background is white but let's immediately make it black so it's easier for our eyes by giving the safe area View view a class name equal to BG primary there we go that's better and we can also give our text items a text off white so it's easier to see them there we go this is our flat list you can see how customizable this flat list is and I didn't even show you half of the things that it offers we can immediately pass the data in we can choose how the data will be rendered and then we can also form the header component for that list there's more more stuff coming soon let's also render an image right below this view by adding another view that will have a class name equal to margin top of 1.5 and within it we can render a self-closing image which of course we have to import coming from react native and we need to import images at the top by saying import images coming from slash do slash constants and images or no I think it's just coming from constants since we have the index that exports them we can now give it a source equal to images. logos small it's not that small right now so let's give it a class name equal to W9 and h-10 and give it a resize mode equal to contain there we go that's better now we have a proper header we want to go two views down and we want to implement our search input component this will be similar to our other text inputs that we used within our signin and sign up but just a tiny bit different so let's create a new component within the components folder called search input. jsx and we can start by entirely copying the entire form field and then making some modifications to it first let's actually show it within the home by rendering the search input like this and of course we have to change the actual name search input and also we have to export it as such so now if we go back it's going to give us the Auto Import which is good and now we can see it barely at the top so let's go into it and let's make some slight modifications in this case we don't need this outer view with the text the only thing we need is one View and the input within it so we can delete this outer View at the end of the classes for the view we can give it some space like space-x -4 and I think the rest can be the same we can also give additional class names to our text input we'll give it a class name of text base margin top of 0.5 text- white Flex -1 and font DP regular now here is where things change instead of having this title we will render another touchable opacity which we have to import from react native so let's get it right here touchable opacity it has already been imported within it we can render an image that will have a source equal to icons . search let's see if we have imported icons at the top we have let's also give it a class name equal to w-5 h-5 and you know it resize mode off contain there we go now we can see the search icon for now we can leave it as it is and later on once we implement the search Logic we can add additional stuff to this search input for now let's go below it and let's continue with our homepage below the search input we'll create another view and this will be for our latest videos section so let's give it a class name equal to w-o flex D1 padding top of five and padding bottom of8 within it we can render a text element that will say latest videos and we can give it a class name equal to text- gr-100 text- LG font DP regular and margin bottom of three and if memory serves you right the next section we have to implement is a horizontal list of videos and also let's add a placeholder to this input so we can quickly jump into the input so we can replace the placeholder with something like search for a video topic and there we go you can see it right here now going back to home how are we going to implement that horizontal video list well right below our text we can create a new component so let's create it in the components folder and let's call it trending jsx we can run rnf and we can import this component right here trending and of course we have to import it at the top as well that's going to be trending coming from components trending to this trending we can pass a posts property that will be equal to some kind of an array where we can also have a couple of different things let's do just IDs now to keep it simple for example id1 let's also do another object with an ID of two and then another one with an ID of three and we can say question mark question mark meaning if it doesn't exist then make it an empty array just so it doesn't break now we can dive into the trending and we can map over those elements in another flat list so we know we're getting the posts right here as a prop and the only thing we'll render will be another flat list we already learned how to work with that right we have to pass a data which will be equal to posts we need to give it a key extractor which will be equal to a function where we get the item and then we take over the item. dollar sign ID as that's how the items will look like coming from aite and we have to give it a render item meaning how each one of these items will look like once we destructure it and map over it for now I'm going to copy what I have right here at the top it will be just a single text element since we don't have a lot of data to show right now and there we go you can see that we have another flat list right here but the most most important thing for this flat list will be transitioning it to a horizontal view simply by giving it a horizontal prop you can now see latest videos 1 2 3 that is great so now we have a horizontal list and we have a vertical list right here and that's actually the primary reason why I wrapped everything in one flat list instead of wrapping everything in a scroll view as we typically should do that's because scroll views don't support both horizontal and vertical scroll at the same time and in this case since we have a flat list with vertical scrolling this one right here and another flat list within that flat list that supports trending or horizontal scrolling this is the way that we needed to do it there's a special error in react native if you wrapped everything in a scroll View and had two different flat list types like horizontal and vertical you would get a special error saying that you cannot do that so with that mind let's go below this trending and below the list header content as well and let's use another special flat list property called list empty component it allows us to create a function inside of which we can specify what will happen if our list is empty so we can say something like text and then say empty now this doesn't show right now but if we mod ify this data to be simply a completely empty array I'm going to commment this out and remove it and make it empty now you cannot see anything but if we give this text a class name with a text off white you can see it says empty but come on let's make this look a bit better let's create a new component that we will call empty state jsx we can run rnfe and we can import this empty State and show it as the only thing right here empty State coming from components we can pass it a title of no videos found and we can also pass it a subtitle of no videos created yet or we can say something better like be the first want to upload a video now we can navigate over to this empty State Implement a view with a class name of justify Center items-- Center and padding X of four within it we can render an image coming from react native of course and we also have to import images coming from do/ constants and we can render the image with a source of images. Mt with a class name equal to W of 270 pixels and H of 215 pixels with a resize mode equal to contain and there we go now we can see that we cannot find anything let's also add a text element to make it a bit clearer and as a matter of fact we can copy these two text elements we had in the homepage right here text and text we can paste them here and we can indent them properly the first one will be a small text with P medium gray 100 and it will render the title of course that title will be coming from props and subtitle too the second one will be text XL with a text Center property font DP semi bold text- white and margin top of two to divide a bit from the top and it will render the subtitle no videos found be the first one to upload a video I think it might make more sense to modify the subtitle to be the title and title to be the subtitle that way we can see no videos found be the first one to upload a video and we can even change them around there we go this makes more sense finally we can render a custom button which is now super simple as we have already created that component before we can import it at the top by saying import custom button from SL custom button and of course we need to pass some props to it props like title of back to explore or even better since we say be the first one to upload a video we can say create video we can give it a handle press equal to a callback function where we call the router which we have to import at the top by saying import router from Expo router and then we can call a push method on it and we can push to forward SLC create we can also give it container Styles equal to w- full and margin y all five there we go that's looking great also it seems like it's not taking the full height of the screen so I can go back here to Safe area View and maybe add a border of two and border of red 500 just so I can see how it wraps it yeah you can see it's missing a bit of height right here if I add ag-h full it should make it full height there we go that's better and we can remove the borders as now we know how things look like and that's another Pro tip if you're struggling with positioning adding borders is always helpful with that in mind our empty state is now done which is great we can kind of move it around scroll it up and down but for now I'm going to bring back my array of three fake items that's going to look something like this that way we don't see that empty State and the last pretty cool thing about the flat list is that you can also give it a refresh control control inside of which we can render a refresh control component coming from react native and we need to create some special props that we can pass to it I'm going to explain what this does very soon I'll create a use State field that's going to be called refreshing and set refreshing at the start set to false and I'll also create a function called on refresh which will be equal to an AS link Arrow function there we can simply set refreshing to true and later on we'll be able to recall our posts or videos so we can see if any new videos appeared once that is done we can set the refreshing back to false so why are we doing this well we can now pass it to the refresh Control Function we can say refreshing is equal Al to refreshing and on refresh is equal to on refresh and if we save it and if we import Ed State at the top coming from react you can now scroll up and later on once we have real videos to fetch once we implement this recall videos function it will actually try to refetch and show you new videos you might be used to this on platforms like Instagram Facebook even Tik to if you scroll up and release it it will start loading new data and I will teach you how to do that very soon as soon as we start fetching real data within our application and now that our homepage is basically done I think it's the perfect time to do that so let's create some data and let's fetch it from within our application very soon we'll Implement our own screen to upload our own videos directly through the platform but for now I just want to ensure that we can see some videos on the homepage and the quickest way to do that is to create a few documents directly through appit dashboard so let's go to databases enter our single database go to the videos collection and click create document in the read me down below you'll find a section where you can also find the data for a few of these videos that we will add so let's copy it one by one first I will add a video with the title of how AI shapes coding future with a URL of this thumbnail and enter a video URL as well and finally I will enter a prompt that I used to generate this video that is the whole idea of the application to share different prompts and videos that you have generated somewhere else using AI or you can also share your own videos You'll also see that this video is actually mine I recorded it but it doesn't matter the most important thing is that we can upload it and see it within our application and finally choose a Creator since you only have one user now it's going to be you does this make sense find the read me down below copy the data and let's create a couple of videos of course if you want to you can upload your own videos and thumbnails but just for the app to look good I have prepared some for you so let's click next and let's click create and our first document containing our video has been uploaded let's do at least two more the second one I will do is get inspired to code with some kind of a thumbnail prompt and a video URL and I'm going to add myself as the Creator and the last one will be a dation which is a dog breed with a thumbnail video URL and a prompt and I'm going to choose myself as the Creator as well and let's click create there we go I think three videos are enough for us to start showing some data within our application so let's go back to the code let's close all of the currently open files and let's navigate over to aight here we have to create and Export a new function that will fetch all posts by saying export const get all posts which is equal to an async function with a try and catch block where in the catch we throw a new error with an error and in the try and in the try we can say const posts is equal to await databases. list documents and to it we need to pass the database ID which is under config do database ID and we also have to provide the config do Video Collection ID and I don't want to every time say config Dot and then config do as well what we can do is simply destructure all of these values from the config object so I'm going to copy them all say con destructure them like this and of course you have to provide commas at the end of each one and then say equal to config this will allow us to expose them outside of the object so now I don't have to say config dot rather I can just refer to them like this finally we can return posts do documents this is great we have a function that fetches all posts so how do we actually use this within our application well let's go back to home and let's give it a shot I'm going to write it right here at the top of the file first we need to create a new use state which will call data set data at the start equal to an empty array and we also need another use State for the loading so is loading set is loading and it's going to be set to true then we need to create a use effect within which will fetch that data as soon as the component loads or the screen in this case so we can say use effect like this with a dependency array that's empty meaning only fetch it at the start and don't forget to import use effect from react within here we can create a function const fetch data if is equal to an async function like this and then we can immediately call it right below fetch data the reason we need to do this is because you cannot use async code directly within a use effect this would be illegal and wouldn't work you have to create a new function inside of which you call asynchronous code here we can set is loading to true because we have started fetching the data and we can open up a try catch and finally block whether we succeed or fail we want to set is loading to false because we're done fetching in the catch we can call the alert coming from react native do alert error and we can render the error. message and in the try we can say const response is equal to a wait how did we call our function get all posts coming from lib ight and then once we get the response we simply set the data to be equal to response and just like that we have data about our videos so what do you say that we conso log it right here below I'm going to say consol log data we are here I'm going to open up the terminal and would you look at that the data that we have added within aite is right here we can see it by how AI shapes coding future the video you L and everything else that means that we can now start modifying our jsx to actually show some thumbnails and videos instead of showing Simple Text elements but before we do that I want to give you another Pro tip we can further optimize this code and make it more reusable by converting all of this into a custom hook if you think about it we'll have to fetch data in a lot of different pages in the profile in the search and in many more cases and the only thing that will change is the actual function of which posts or which users or what data are we getting so with that in mind we can copy this entire consol Lo data and the use effect and these two states and remove them from the home to clean it up a bit what we're going to do instead is create a new file within lib called use aite .js this will be a custom hook so as with every custom hook it has to be a function that starts with the word use in this case I chose the name use app right and as a parameter we're going to get a function that tries to fetch something so I'm going to call it FN and within here I'm going to paste everything we had before is loading States use effects alerts and of course we have to import use state from react we have to import use effect from react and instead of conso logging the data we will simply return it for now we can say return data within an object like so and then we can say export default use aite now where will this get all post come from well we will pass it as a function through props so instead of calling get all posts let's call FN like this now going back to home instead of all the code that you've seen before that was here we can do one single thing and that is const get the data and rename it to posts which is equal to use aite custom hook to which we pass this function of get all posts which we created not that long ago it's basically just this one so before we had about 203 30 lines right here and now we have moved that logic here we're passing the getter function and we can try to calog the post one more time to see if we truly get them we have renamed it to posts so I open up the terminal and you can see there's a lot of code so that must mean that it has actually done it for the second time there we go so the logic works the same but we have extracted it to make it more reusable we can also make it more powerful by creating this function called refetch const refetch is equal to a callback function that simply calls the fetch data one more time which is the same exact function which we have created for fetching the data for the first time but if we want to use it here we have to bring it out of the use effect so we're calling it once at the start and we're calling it whenever the refetch function gets called and do you know when that will be well it will be on refresh once we pull our device up so with that in mind let's return the data that is loading as well as the refetch and back in home alongside just getting the posts we can also get refetch and we can recall videos whenever we scroll up or swipe up so we can say await refetch there we we go I hope this makes sense I know it's a bit more advanced creating custom reusable hooks but I hope it will make even more sense once we use this custom hook for the second time so you can see how much code we have actually saved ourselves from writing with that in mind instead of just doing a constant log in the terminal which doesn't mean too much let's try to actually show some data within our flat list and then instead of rendering the ID we should be able to render something like title and there we go how AI shapes coding future get inspired to code and the Dalmations journey through Italy that's great but we can do better than that we can also show the thumbnails we have uploaded so instead of Simply showing a piece of text let's create a new component called video card. jsx where we can run RN Fe and we can import it right here as render item video card make sure to import it at the top right below empty State video card coming from components video card to it we can pass the entire post or we can call it a video equal to item so now we have access to all of this data within a video card and we can destructure it video right here we can also automatically destructure the properties within the video such as the title thumbnail video and Creator and outside of the Creator we can pull the username and the Avatar pretty cool stuff right now we can use anything we need so just to verify this is working let's give some class names to this view like a class name equal to flex-all so they show one below another items Das Center padding X off four and margin bottom of 14 and let's try to render a text with a class name of text- toxel text- white and let's make it render the title there we go everything is working exactly as we thought it would now let's put that text to the side for now and let's create more structure for our cards by creating another view with a class name equal to flex Das row g-3 and items Das start within it another view that will have a class name equal to justify Das center items Das Center Flex D row and a flex of one and within it last view trust me a view with a class name equal to W of 46 pixels h of 46 pixels rounded - LG border border D secondary we can start seeing things now justify center items Das Center and a padding of 0.5 within it we can render an image coming from react native with a source equal to URI is the Avatar class name is dou - fo h- full and rounded dlg and resize mode is equal to cover and now we can see J as in JS Mastery this was created automatically for us by aite let's go one view down below the image and let's create another view this time for the title of our video with a class name equal to justify Dash Center Flex -1 margin left of three and GAP y of one within it we can render a text property that will simply render the title we can also give it a class name equal to text- wide so we can see it font DP semi bold and text- smm and now we can remove this second title as we have the real one above there we go we can also give a special property to to this text which is a number of lines one which stops the text from going further if it's longer below the text of title we can render another text and this one will render the Creator or in our case the username we can give it a class name of text- XS text- gray 100 and font DP regular and we can also make it fit in one line number of lines is one there we go that's good we can go below this text and one two views down and we can create another view this one will have a class name equal to padding top of two and we can render an image that will have a source equal to icons coming from constants do menu make sure to import these icons class name equal to w 5 and H of five and a resize mode equal to contain there we go just so we can do some additional actions moving two more views down right here we can finally show the video and this will be interesting first we don't want every single video to play right off the bat so we want to create a new state to ensure whether the video is playing or not so let's create a new use state snippet called play and set play at the start set to false we need to import the used State and for now let's see what happens if the video is not playing so we can open up a new Dynamic block of code where we check play and if it's playing we can show for now a text saying playing else we will show something else we will show a touchable opacity which is basically like a button that will play it but instead of it being a button we will actually show the thumbnail so once you click on it you can start playing let's not forget to import touchable opacity from react native and within it let's render an image that will have the source equal to URI off thumbnail we're going to also have a class name equal to w-o h-o rounded Das excl and margin top of three with a resize mode equal to cover and immediately you can see that it takes more screen but we cannot really see anything happening right here so let's apply some additional class names to this touchable opacity such as a class name equal to w-o and there we go we can already see the thumbnail h-60 for the height rounded Das Excel margin top of three relative justify Center and items Center and now we can actually move through three of these thumbnails and our app is starting to look better and better below that image will show another image and this one will have a source equal to icons. playay you can see this play icon so for the images if the source is a URL you have to do it like this say URI and then point to the URL but if it's a local image you can just do source and then point to the path to that image let's also give it a class name equal to W12 h12 and absolute and a resize mode equal to contain there we go so now it seems like we can click to play it to our touchable opacity we can also give the active opacity of 0.7 so once we kind of hover over it or click it we can see what's happening and on press we can call the Callback function and set play to be equal to true for now that will just turn it into a text and let's also give it a class name so we can see it of text white so if we click play on it you can see that now it says playing and we can repeat the process for every single one of these three videos that is phenomenal let's also go back a bit now it always says playing because it's stuck but if you open up the terminal and press the letter R it should reload it automatically log Us in and we can see our thumbnails once again this is great we can also fix this warning at the bottom regarding keys but for now before we get this video is actually playing what do you say that we implement this latest videos section that's this section right here it's going to show not the latest videos but the trending videos and it's going to show them in a bit of a different format it's going to be a horizontal list where you can swipe left and right to see different videos in a portrait mode so let's Implement that and then we'll figure out how to get those videos to play do you know where we have to go to start working on these latest videos well it's going to be within our flatlist and within our trending comp component right here to it we could pass the same posts that we are getting from the top like posts but let's create a different fetch function so we get some different posts to show right here I'm going to go back to aite and instead of get all posts we're going to create a new function called get latest posts but for now I'm going to start with it by duplicating the get old posts one there we go we have it right here I'm going to collapse this one and and rename this one to get latest posts you can call it get latest videos as well everything is going to be the same besides an additional query that you can pass right here do order descending and you pass a function of dollar sign created at and we're going to query a limit of only seven because we only want to show the latest few videos that's it so now let's go back to home and let me show you how easily we can fetch those posts now that we have created this reusable custom hook you basically just duplicate it we can rename posts to something like latest posts and we don't need a refetch from that and to it you pass get latest posts coming from blip aite and that's going to give you a completely different set of posts in just a single line so let's now use those latest posts and pass them over to our trending component there we go now we can navigate into the trending and we can implement the structure and the presentation of how we want these elements to show of course the end product being something like this first things first we're going to install this great package called react native anima table it allows you to add animations to your react native applications and installing it is quite simple we can just go to our clean terminal and run mpm install react-native Das animat table and while we're here we're going to also install another package that allows us to play videos within our application it's called Expo DAV I think that stands for audio video and let's press enter first things first we can import everything as anima table from react native anima table and then we can create a new component right here const trending item is equal to a react Arrow function where we can return a new anima table. view which basically is a view that allows you to do animations within it let's properly close it and instead of rendering a text for each one of our elements we can now render the trending item and to it we can pass a couple of things we can pass the currently active item which will come from the state so we can declare a new US state snippet called active item set active item at the start set to posts zero so the first post out there and then we can pass the active item and we can pass the item as well moving back we have to import use state from react and we can get access to our active item as well as the item within this anima table view we can give it a class name equal to margin right off five and we can declare an animation which will be equal to essentially an object which we want to declare and that object looks something like this const zoom in is equal to an object and we can provide multiple different states zero state with a scale of 0.9 and then we can add a one state with a scale of one similarly we can duplicate this and create another animation called zoom out where at the start we're going to start from a scale of one and move to a scale of 0.9 which will basically Zoom it out now within this animation if the active item is equal to item do dollar sign ID so if we're currently at that it item we want to zoom it in else we want to zoom it out and we want to do that with a duration of 500 milliseconds then as we have done before we have to ensure whether we're playing the video or showing its thumbnail so let's create a new used State snippet called play set play at the start set to false and then if play is turned on we can return something like let's do a text that will say playing let's also give it a class name equal to text- White else if we're not playing we want to create a touchable opacity like before that will allow us to play something so let's create a new touchable opacity coming from react native with a class name equal to relative justify Center and items Center active opacity will be 0.7 and on press we want to have a callback function that will set play to True within it we're going to use a new component we haven't used before which is the image background so we're not using just the image we're using the image background that will have a source equal to URI of item. thumb nail let's also give it a class name equal to W of 52 h of 72 because it has more height as it's a portrait rounded dash35 pixels margin y of five overflow of hidden Shadow dlg and shadow-black D40 to make it appear like it's floating and there we go you can start seeing those portraits images let's also give it a resize mode equal to cover now as it's a flat list and as it's a horizontal flat list you can immediately just use your finger I was about to say mouse to swipe through them and if you go back to trending I think that's right here if you remove this horizontal you can notice that they should start appearing vertically there we go although it's quite hard to see them there we go that's better but of course we want this first one to be horizontal and then we want the bottom one to be vertical great below it let's also add an image with a source equal to icons coming from the icons constants doplay and of course we have to import image from react native let's also give it a class name equal to W12 h12 and absolute so it shows on top of the image background with a resize mode of contain that is looking great now as you scroll over them you can see that looks good but for some reason it looks like it's not applying this animation because if I just go for zoom in right here you can see that they're all enlarged but right now it doesn't seem like any of them is and keep in mind this is the UI we're going for so let's check the active item by giving us a console.log active item and let's also cons log the item that dollar sign ID like this now we can compare the two by pressing R to reload we get all of this data from before but somewhere on top of it we should be able to see just those IDs I'm after let's first remove the other conso log that I think we have right here within the homepage or maybe within the use app right let's see no that's not it where is this conso log hiding let's search for it console.log we have one right here in trending which is the one we created right now we have the error and then we have error and error okay that's good so we don't have any additional conso locks maybe these are just old ones but no they seem to appear every time which is quite interesting oh maybe that's because this is this active item yeah the active item could be the actual element so we might need to do active item Dot and then dollar sign ID let's try that there we go that's good so now we get this ID and we get the second ID and only for the one that matches we should make it enlarged so let's see if we try doing active item do dollar sign ID there we go now that one is big and if we switch over over it additional ones don't change so we want to actually change this as we swipe and maybe at the start we make the second one bigger by changing the active item to one right here that way it's more similar to what we have in the design but how do we actually use this set active item so that they modify once we scroll well let's create a new function const viewable items changed this is pretty amazing you're basically given this Handler immediately by the flat list I mean what doesn't the flat list do so you can say on viewable items changed and basically this is called when the viewability of rows changed defined by the viewable row so let's say on viewable items changed we call our viewable items change function and let's say changed not changes there we go as the parameter we are getting the item so we can destructure the viewable items from it and we want to say if viewable items dot length is greater than zero meaning if we have more we want a set active item to be equal to viewable items z. key right below it we also want to modify the viewability config where we can give it the item visible percent threshold on off about 70 and we can give it the content offset to figure out when do we actually apply that visibility percentage by saying like X is about 170 pixels now if we go back the active items are not what they used to be now they should be the actual key of that item so here we no longer have to use the ID that I added before and if I save it you can see now the middle one is enlarged but if I scroll they actually change and in case you want to make it even larger you can modify the scale even more for example scale 1.1 or even 1.2 and you can see how it looks like right now I think 1.1 might be the most we can go for this is actually great perfect so now we have also implemented some animations to our application but the question is how do we now click on it and play it right now we get nothing we have to implement this part right here when the playing is true we have to use this new package we have installed called Expo AV that will allow us to play videos so right here let's use their video component just like so it will be self-closing and it's coming from the top by saying import video coming from Expo AV and another thing we'll use is the resize mode also coming from Expo AV within this video we want to add a source of the video which will be equal to URI item. video but that's not enough on its own let's also apply a class name of w of 52 h of 72 so the same size as the actual container rounded -35 pixels margin top of three and background white over 10 there we go so now we can see the video right here this one is horizontal so it looks a bit different on the vertical view but that's okay we can add a resize mode equal to and now we can use this special component called resize mode coming from the Expo AV and use the dot contain functionality we can also say use native control as well as should play so the video should play and that way it plays immediately once you click on it and we can also say on playback status update we get access to the status and if status dot did just finish I like the naming of these variables it's very descriptive um if it did just finish we set play to false which should bring us back to the view of the actual thumbnail there we go it's easier than we thought right so now if I go here if I click on it the video loads and it starts playing this one looks better as it is in vertical View and it looks amazing you can also Zoom it in and go full screen I mean how cool is that your own video sharing platform these are just short shorts let's try with this one there we go you can also Zoom it in you can play audio I'm going to mute it for now and play rule number six if the plan doesn't work change the plan but never the goal yep I hope your goal is to become a professional developer which is exactly while you're watching this video and here we have another one where we can also go to the start expand it and the coolest thing is you can actually rotate your phone and see it in full screen if it's horizontal this is great and this is a pretty cool video generated by Sora using AI so this is a beautiful latest video section now let's focus on trying to play these videos below we can do that by copying this video component closing all the currently open files moving back to home and going right here within our video card and going to the part where we actually play something we can paste this video component we can modify it a bit URI will simply be video class name will be full width this time so w full h60 rounded XL and margin top three we don't need the background in this case the resize mode will be contained don't forget to import the resize mode from Expo AV as well as the video also so coming from Expo AV we can do that at the top we can use the native controls should play and then we also use the same on playb status update so now if we save it and if we play let's do this horizontal video and click play it actually opens up and as you know you have full controls and you can turn your phone around as you normally would with any kind of application that you're already used to to view it in full screen this is great we can also do something like that for these videos right here perfect let's see what happens if I click on another one okay that one is now playing and make sure to mute it as there's loud audio coming from this YouTube short but these videos are also playing from before which is totally okay we can have multiple videos playing on this screen this is looking great and I especially love these portraits right here at the top with this slight animation for some reason they disappeared now which is a bit weird but I do think they're coming back and don't forget if you reload if you pull it to the top it will refetch all of these videos at the bottom there might be some tweaks which we can still modify and improve but for now this is amazing I am very happy with the homepage that we have created if there are some tweaks we might need to make we can do that soon next pages that we have to implement are the search page so once you search for something you want to actually show the screen showing only the videos matching that search term and then also there is the profile page to which you go to if you click this J or another Avatar right here whatever your name is and of course there's the create page which is basically one large form that will allow us to manually upload those videos and not only view those that we have created from aite so let's do the search and the profile next because I want to show you how easily we can reuse these video components we have created so far and then after that we can focus on the create phenomenal job so far leave a comment down below if you're watching until this part of the video keep it up to get started with our search we can navigate over to app search and then query right here can you see how this file is within square brackets well that means means that we can extract the value of that search out of the well not URL but out of the screen so how do we do that well in react native you can say const query is equal to use local search perams and this used local search perams is coming from Expo router so let's import it use local search for Rams from Expo router what we can do right now is simply make this text a bit larger by giving it a text 3XL as well as text- white and within it we can now render this Dynamic query so let's see if that works what we want to do is navigate to this Dynamic page and if I'm not mistaken we haven't yet implemented the logic within our search input component it looks good but we still have to make it do something on click so right here instead of using this password we no longer need that we can get access to the path Name by saying con path name is equal to use path name like this and we call it as a hook this use path name can be imported from Expo router so import use path name coming from Expo router there we go that's good and and we also can create a new use State field and we can call it query set query at the start equal to let's do just an empty string we don't have to pass any props into this search input so let's delet it and then here where we use the value we can rather refer to the query we don't have to make it secure text entry and on change text we simply want to get the event and set the query and pass that event we can also change the placeholder text color to Hash CD CD e0 which is going to make it pop just a bit then in the touchable opacity we can add an on press this is as if we were adding a click Handler on the button on press is equal to a callback function where we check if query exists or rather if query doesn't exist then we can simply return an alert coming from react native. alert and we can give it a title of missing query and a message of please input something to search results across database that way if a user doesn't type anything it should give us an alert next outside of that if if path name that starts with for/ search that means that we are already on the search page and in that case we simply want to set the search per Ram by saying router. set per Rams and in an object we set the query let's also import router from Expo router and else if we're not on the search we want to say router. push and we want to push over to a template string of SL searchquery and now if you go in click on this field you're going to get this nice orange glow and we can type something like let's see what do we have ai maybe Ai and click search by pressing on the magnifying glass you can see we are redirected to the search page and right now the text is not that visible so let's make it a safe area view coming from react safe area view with a class name of BG primary and h-o and now you can see that we have ai exactly like we typed if you go back and type something like test maybe and press search you can see that now we are on that page where the query is equal to search that is great that's enough information for us to be able to fetch or all of the corresponding posts with that in mind let's head back to aite and let's Implement a function that searches through posts to do that we can duplicate the function that fetches the latest posts and rename it to search posts and it will accept the query as the first and only parameter we do the same thing here we call databases. list documents provide the database ID and the collection ID of the documents we're driving to fetch and then instead of order we're going to use a query. search we're going to searge by title and we're going to pass the query as the actual search term believe it or not that is it this should give us all the posts that match our corresponding query that means that we can now go back to the query and call are used ight hook to get all the necessary information but if you look at our design you'll notice that our search page is almost exactly the same as our homepage it has the same search right here with a search THM type in already it also has the heading and then it has the flat list the only thing that's missing is the trending videos so we'll basically be able to copy the homepage and make some slight modifications to implement the search page so let's do exactly that I'm going to head over to home I'm going to copy the entire file and I'll paste it into search first things first modify the component name or screen name from home to search we can do that here we don't need two different fetches we need only one where we call the search posts function coming from lib arite and we also have to pass a query to it and where do we get the query from well we already know that that we have done it already const query is equal to use local search prams which is coming directly from Expo router import use local search prams coming from Expo router that way we get the query then we use the use app right hook to make a call to our search posts and then we get post right here we also get this refetch and we can refetch not by scrolling up rather we can do a simple use effect right here with a callback function which will be called every time that the query changes so every time that the user types something new we can just call a refetch function now if we save this of course everything will be broken first of all we don't have this refreshing so we can remove this bottom part that's going to temporarily fix it and let's navigate over to query to see how thises that look like I'm going to type Ai and press search and of course we get a couple of Errors first we don't have the latest posts which we pass over to trending so we can completely remove this view that says latest videos but before we try to do another search let's go ahead and see what other things we have to change starting from the top we have a safe area view with a flat list that shows items vertically by default we extract the IDS we render the video card item and then we list the header component the header is not going to say welcome back rather it will say something like search results and then below we can say query so kind of giving search results for this specific query and then right below this text we don't even need this logo we can immediately present our search input so we have a text and immediately below that text we can render our search input this time we'll have to pass it an additional prop of initial query equal to query that way we can accept it right here initial query and if we do have an initial query we can set this query by default to be the initial query to autop populated that way if we come from home it will be pre-populated to sa the search term we searched for then let's see the structure here we have one view with margin Y and padding X we don't need a spacing here and we don't need this entire inner view so we can close the opening and closing brace we also don't need this opening view right here so we can remove it and let's indent everything properly so it's easier to see I'm going to make multiple selections and then do it like this so we have the view we have the text that says search results immediately after we have a text that says query and then below we want to have a view that will create some spacing with a class name of margin top of six and margin bottom of eight and within it we want to put the search input there we go and finally we have the empty State no videos found but this time we can say something different like no videos found for this search query see how good it is to make reusable components we just have to change the prop that we passed to it with that in mind let's give it a shot let's simply open up the keyboard and say Ai and click search as you can see we are redirected directly to the search page which looks great by default but we also have to get rid of this Stop Bar I think we can do that with within our primary layout yeah you can see here stack search query we have to uncommon this which should get rid of the top bar I think if we remove this forward slash it will work there we go that's good and we can immediately see the search results for the term AI the AI is also pre-filled but for some reason it says no videos found that's interesting so our search post fun fun this one is not returning any videos that match by title a quick way to debug it is to go here and check if AI is within some of these titles and it does appear to be that way here we have a title of how AI shapes coding future inspired to code I guess kind of code or Cod is right here code and here is coding so maybe if we try that we should hit two of these videos let's give it a shot I'm going to say Cod start off code and coding and still we get a possible unhandled promise rejection export default trending alert doesn't exist this is actually quite good as we can just search for alert and see where it is being used sign in sign up home we're using it here or at least we're importing it but we're not using it in the query also not being used we have this search input are we using it here yeah it's coming from react native that's looking good and we have this use app right as well oh it looks like we don't have it here so here we have to import alert from react native and once we do that we get another error saying that the function is not defined which is very useful because now we can go back to our I believe it's query file and it's basically saying that the search post is not defined even though it's coming from here and it does seem to be defined we're also passing the query to it oh this is a good one so what I've done here is a typical rookie mistake what we have done before is we're just passing the function to the use app right which we then later on call it's similar if we pass for example get all posts right here we pass the entire function declaration without calling it that way here it gets replaced and it gets called but what I've done now since I had to pass the query is I've actually called the function before so instead of passing the function declaration I'm passing whatever the output of this function is for example an array of some posts right and then that ends up getting all the way to here and it tries to call an object which is not possible so if you need to pass some data into the function when you're sending it over over you can do that by defining a callback function like this it might be a bit harder to see so I'm going to put it in a new line use aite essentially you're passing the entire callback function so once this gets called the entire declaration will get passed and it will properly call it right here I hope that makes sense so now we can give it a second shot let's say something like Ai and and search okay it says something like search for attribute title requires a full text index and that means that we have to go right here to databases go to the videos collection and go to indices and create a new index we can call it something like search by title the index type will be full text as the error message said and the attribute will be by title and let's click create it looks like the index name needs to be properly indexable so let's do search uncore by uncore title and click create there we go the index was created and this should allow us to do searches back in the code I will type AI one last time and this time we don't get an error which is great but we also don't see any videos so what we could do is is we could conso a couple of things we can conso first of all the query to see if the query is good and then the posts that we got back to see if there is anything to show once we do that you can see that the query was all right but the array was empty let's try to search for something like C for coding and this time we do get back to videos the how AI shapes coding future and get inspired to code which is exactly what I wanted to get back interesting how it didn't get as AI let's try one more time no what if we do both letters uppercased what if we do Italy I know that's another word from our titles okay that works that's interesting maybe it's trying to search for more than two characters let's see what else do we have here inspired Journey let's say search for inspired that is great and let's also search for Journey perfect basically everything is working but for some reason search for AI didn't work but at least that showed us that our no videos screen is working as we get no videos found and then create video so that is great let's go back to homepage one more time we can see different posts we can see the latest videos as well and we can make a search and you get a complete search similar to the homepage but in this new layout where you can keep searching for whatever you want to find by simply deleting it and searching again or you can swipe left to go back to home wonderful it wasn't that tough to create search once we have reusable video card components reusable flat lists and also reusable hooks that allow us to more easily fetch the data we can also clean things up a bit as our query is a bit smaller than our homepage we don't need things like the image refresh control or alert we don't need to use State images trending and all of these other calls from aite I always like to keep my code clean and have zero unused variables the next screen we can focus on will be profile so let's click on profile right at the bottom right corner and we have an empty screen let's turn it into something that looks more like this where we fetch the Avatar username the number of posts and some fake views and also display all of the videos that that user has created to do that we can copy the entire code from our creatory file close all of the currently open files and navigate over to profile there we can override the entire code with what we copied from the query and rename it to profile right here and also right here at the top that should immediately give us something better to look at there we go it says no videos found it says search results but let's first make it into an actual profile by modifying which posts are we trying to get we're not trying to get the post that we search for rather we're trying to get the posts that our user has created so let's navigate over to aight duplicate at the search posts right below and let's call it something like get user posts where we can pass the user ID so we know which user posts are we getting we also list the documents coming from database ID with this collection and query. equal where the Creator is equal to user ID that's it you can see how simple it becomes once you understand how all of this works now we can go back to profile and instead of fetching these posts and refetch from search posts we can simply call get user posts coming from lib out prite like this and to it we're going to pass the user ID but the question is where do we get the currently logged in user ID pause this video give yourself a moment and try to figure it out I'm GNA let you know in three two one it's coming from the global context it is right here remember under values we're passing the user as the object we can get access to it and the user contains the ID so we don't need the query in this case rather we can say const d structure the user the set user and the set is logged in because from here we'll also be able to log out and we can say that's equal to use Global context which is coming from our context it doesn't want to autoimport it but we can say import use Global context from slash no it's context Global provider and then we get the user. dollar sign ID and this should give us access to all of the posts looks like it redirected us back to home so we can click to go to the profile again and it is going to complain about the query we no longer need this use effect with a query let's save it now and go back to profile it's going to complain again because we're using a query in a couple of places so let's simply comment out the query here and here and I think that's it if we save it and click profile once again we can see our three videos that we have created which is exactly what we wanted so now the last thing we have to do is change the header of this flat list displaying our posts into something that looks like this we basically want to add this user card at the top that lets us know that we can log out and that we're currently on the profile page we can do that by modifying the list header component part of our flat list in this case let's delete everything we have in there right now to make it a bit easier for us to develop it and we can first wrap everything in a view that view will have a class name equal to w- full justify Das center items - Center margin top of six marging bottom of 12 and padding X of four within that div we can show a touchable opacity that looks something like this and we import it from react native within it we can show an image with a capital I also coming from react native with a source equal to icons Dot and don't forget to import icons from constants do logout with a resize mode equal to contain and a class name equal to W6 H6 you can see this log out on top let's also put it at the End by styling detachable opacity by giving it a class name equal to W full items end and margin bottom of 10 that way it's at the top right also later on to this touchable opacity we'll have to provide a function that implements the logout functionality so let's simply declare it right here const log out is equal to a function that looks like this and we call it on press great now below this touchable opacity we want to show a view where we render the users's Avatar so let's do just that view with a class name of w16 h16 border border secondary that looks something like this rounded dlg justify Center and items Center and within it we can show a new image property that has the source equal to an object of URI is equal to user question mark. Avatar that's going to look something like this it's not visible until we give it a class name equal to w- 90% h- 90% as well within square brackets that way it's not going to take the full width of the screen and round it- LG and resize mode equal to cover okay this is great and right below that image and below this view we can render a new custom component called infobox so let's create it new file infobox jsx where we can run rnf and we can immediately import it right here info box make sure to properly import it at the top info box coming from info box we don't need the usif effect the search for Rams nor the text right here that's good if we save it there's going to be nothing there but to this info box we can pass a couple of props like title is equal to user question mark. username container Styles equal to margin top of five so we divide it a bit from the top and title Styles equal to text- LG as this will be a bit larger title Styles below that info box we'll create a view that will have a class name equal to margin top of five and flex row and here we want to show two more info boxes so let's simply copy this one paste it once and also paste it twice the second one will render the number of posts that we have so posts. length or zero if we don't have any we're going to also give it a subtitle of posts container styles of margin right of 10 title styles of text- XL and finally the last info box will show a number of followers we can say something like 1.2 th000 with a subtitle equal to followers we don't need the container Styles and it will have a title of text- XL if we save it you basically cannot see anything on the screen right now that's because we're not making use of any of these parameters we're passing but now we have the structure so we know which props are we accepting so going to our info box we can now accept a couple of props such as title subtitle container Styles and title Styles we can render a view with a class name of container styles with a text that will render the title let's give it a class name equal to let's make it Dynamic text- White text- Center font DP semi bold and we can also render all the title Styles we're passing like this there we go we can see JSM my three posts and 1.2 th000 followers and we can create a new text element right below it for the subtitle that will have a class name equal to text DSM for small text- gr-100 text- Center and font DP regular and let's save it there we go so now we can see one primary info box that renders our username we can see our subtitle of posts and title of three and same thing for the followers and with that my friends believe it or not our profile page has been completed it's pretty crazy what you can achieve when you reuse existing components we have reused almost everything our page our routing structure our flat list from home and search and also the individual video cards which don't forget you can also play and make sure to muted every time especially if you're using these videos as they're quite loud so this is phenomenal so finally let's Implement our logout function so we can log out of the application and maybe log in with another account we can do that by creating another aight function we can say export const sign out equal to an async function with a try and catch Block in the catch patch we throw a new error with the error message and in the try we can say con session is equal to await account. delete session and we pass in current we want to delete the current session and return the session that we just ended with that in mind we can go back to profile we can say await and call the sign out function being imported from aite since we're using a weight we have to make this function a sync we also want to set our Global State user to be equal to null and we want to set is logged in to be null or rather false in this case and want to renate to sign in by importing the router coming from Expo router and then right here we can say something like router replace pointing to forward slash sign in if we do that go back to the profile and click the log out icon on top right we have been logged out and if you try to go back you can't because we have replaced the URL not pushed it so this is the difference between push and replace now let's see if I remember my username I think I used contact JS Mastery Pro and I believe it was was 1 23 1 23 23 and I'm going to click sign in and I was right we are back in we can see all the videos loading it says welcome back JS Mastery and I think that JS Mastery part is hardcoded right now so let's quickly copy this use Global context from profile and navigate over to home let's use that same hook and import use Global context from do do slash do do slash context and then Global provider we get this user and then here where we hardcoded JS Mastery we can say something like welcome back comma and then here we can render user questionmark do username oh it looks like it's not there let's check out collection it is username yes JS Mastery is the username we can see that right here so let's say user. username I think that's exactly how we have used it in the profile as well right we get the user from the global context and then we're using it by saying user question mark. username in this case it doesn't seem to appear though so let's try to conso log in right here on top console.log user. username I'm going to open up this and it does say undefined what if I conso log just the user we get null for user and what would I get if I conso log the user on the profile page let's see if I can do that right here consol log user and navigate to profile it's also null and actually my app breaks you can see it here where I share my phone screen it completely crashed saying cannot read property ID of null so I simply reloaded the entire application and logged out completely it looks like the second time that we logged into our account for some reason it didn't set user to the global context let's see why that is here we have the set user and we're setting it once we get the current user that looks good but then if we move over to sign in oh would you look at that I even left myself a comment set it to Global state but I never got around to doing it and we also didn't do it on sign up so I'm a bit confused how it even let me in and kept me logged in this entire time but for some reason it did so let's fix this the only thing we have to do right here let's do the signin first is get the information about the current user by saying con result is equal to await get current user coming from lib aite and then we can set that user to the state by accessing our Global State const set user and set is logged in is equal to use Global context coming from the global context provider like this and this is supposed to be set not sir and now we can simply call set user to be equal to result and we can set is logged in to be equal to true and then we point to home so this is now good and we can also copy these three lines and go to sign up we can paste it right here but in this case we don't even have to get the current user because we're creating it for the first time so we already have it the only thing we do have to get is set user and set is logged in in the same way that we have gotten it here import use Global context and then use the hook that we created right here that looks good to me I'm going to save it and now we should be properly logging in and saving that information to the global context let's give it a shot I'm going to go continue with email I will use my contact ajs Mastery and I think my password is 1 to 3 1 to3 1 to3 let's go ahead and sign in we are right in and as you can see on the top it says welcome back JS Mastery so now it actually knows your username and if you go to profile that looks great as well I use very high res thumbnails so it takes some time to load but for smaller ones it should be quicker so this is great with that in mind the onboarding the sign in and the signup page are looking as good as ever and they're fully functioning right now the home screen is just stunning where we can play different kinds of videos make sure to mute them first we can also make the videos full screen which is pretty amazing if you ask me you can also rotate your device we have also implemented search so we can search for as we said journey and press search that works as well and and finally we have also implemented the profile where you can see what the currently logged in user has created and we can also log out on top right and finally we'll Implement a screen within which you'll be able to upload your own videos and thumbnails and therefore create new documents and add them to our database and then show them within our homepage so let's click on create right here at the bottom and let's navigate over to the create page and let's get started amazing job so far first things first we got to be safe so let's start with the safe area view coming from react native safe area context let's give it a class name equal to BG primary and h- full for full height and let's turn this entire view into a scrollable view by wrapping it within a scroll view component coming from from react native with a class name equal to padding X of four and margin y of 6 right within it let's render our first piece of text on this screen that will say something like upload video and let's give it a class name equal to text- toxcel text- White font DP semi bold and save it there we go that's our title right below it we can render our first form field and this form field is a component that we have created before you can find it here so let's just import it by saying import form field coming from slash do slash components form field we have to pass a couple of things into that form field so we're going to do that through props we'll pass a title title equal to video title and we also have to give it a value and to create that value we can create a new use State field that will be called form set form and at the start equal to an object let's correct the spelling here and let's give this object some default properties such as a title that's an empty string at the start a video which will be null at the start a thumbnail which will also Al be null at the start and a prompt which will also be an empty string at the start let's fix this title there we go we'll also have to know are we currently uploading a video so we can show the loading so let's immediately create a new US state snippet called uploading and set uploading at the start set to false great now let's go back and let's give this form field a value equal to form. tile we can also give it a placeholder equal to give your video a catchy title and we can also give it a handle change text equal to a callback function where we get the event we set the form we spread it the previous values of the form and then we just modify the title to be equal to the event finally we give it other styles equal to margin top of 10 and of course we have to import U State coming from react once we do that and navigate to create we can see our nice looking input now let's create a view below that input and that view will have a class name equal to margin top of seven space y of two to create some spacing and within it we can create a new text that will say something like upload video and we can style it by giving it a class name equal to text-base text- gray- 100 and font dasp medium there we go upload video and then we can create a touchable opacity right below that text which will be our area to click on and upload a video so touchable opacity coming from react native and here we want to see if we already have a form. video if we do we will display a video component coming from Expo AV Audio Video so let's immediately import it at the top by saying import video coming from Expo AV and we also need to get that resize mode coming from Expo AV as well we also need to close this thary operator by creating the second part if we don't have a video we'll create a view that will allow us to upload the video so that's going to be a view and let's properly close this with a class name equal to W full h40 padding X off 4 back CR of black 100 rounded - 2XL justify Das Center and items Das center it's kind of like a rectangle which we can click to upload a video within it we can have another view with a class name equal to W-4 h-14 border border dashed border secondary 100 justify Center and items Center and finally right within it we want to have an image which we need to import from react native so let's get it get a source equal to icons which we need to import from constants do upload with a resize mode equal to contain and a class name equal to W 1/2 and h-1 over2 there we go this is an upload icon and then once we click on that once we upload the video we can start showing it here so we can immediately get the source of that video equal to URI is form. video. n URL URI we can give it a class name equal to w - full h- 64 and rounded -2 Excel we can use native controls we can let the resize mode be equal to resize mode. cover like this and we can say is looping in case we're filling in some other fields and the video is done we wanted to start playing once again with that in mind we want to go below the statable opacity and below the view as well and and create another view this time for the upload of the video thumbnail so let's create some space by giving it a class name equal to margin top of seven and space- y-2 and we can copy this same text element that before said upload video and this time it will say something like let's do thumbnail image make make sure that this is the text with the text Gray 100 font P medium and text base and then right below it we can basically copy this entire touchable opacity that we have created for the video because we want to have the same thing for the image so right below the text we can paste the touchable opacity and instead of checking for form. video we're going to be checking for form. thumbnail if we have the thumbnail we won't be showing the video right we'll be showing the image that we have uploaded with a source equal to URI form. thumbnail do with a resize mode equal to cover and a class name equal to w-o h- 64 and rounded Das to excel okay that's good but if we don't have the image yet we have to fix this second part so for now let's delete this inner view right here and let's just keep the outer view let's change the H to 16 and we can add the border right here border D2 border dl-200 Flex D row and space- X-2 and within it we have the upload image WID a width of five and a height of five as well okay so now we have different views for the video a bit larger and a bit smaller for image and we can have a text right below that image that's going to say something like choose a file and we can give it a class name equal to text DSM text- gr-100 and font DP medium there we go that's much better finally we can copy this form field that we created above go all the way to the bottom below the touchable apacity and below the view and this one will be for our AI prompt that we used to generate this video which we want to share with world so we can say form. prompt and we can say under placeholder something like the prompt you used to create this this video and under set form we're going to modify the prompt instead of the title in other news or in other styles margin top can be a bit smaller like seven and finally below the form field we can render a custom button first we have to import it right at the top so let's duplicate this form field and import custom button from the custom button pass it a title of submit and publish let's also give it a handle press so once we click on it we want to submit it so really quickly here we can create a new function const submit is equal to an arrow function that is good and we can give it container styles of margin top of seven that's going to push it a bit from The Prompt input and we can also give it the is loading property which will be uploading so if we're uploading that that means that we're loading okay this looks good you can see it doesn't fit on my screen right here even though it's a large screen but since we use that scroll view right at the top I can still scroll through everything and see what's happening which is great and this is it for the jsx part or the presentation part of our create video form but of course in this case where the magic happens is with the video upload so we first have to do the logic for uploading videos then uploading thumbnails and then uploading everything to our database so first things first we cannot work on the submit function until we have worked on the actual upload functions so let's create a new function at the top const open picker that's going to be a picker for our video or image file which will be an async function that selects the type of the file file we're trying to pick and we can open this picker once we click on this touchable opacity so we can go right here and say on press we want to call a callback function where we open the Picker this time it's going to be a video picker and we can copy that on press and paste it to the second touchable opacity and on the second one we're going to say open picker image and make sure to properly close it as well there we go so now we can start working on the code within this open picker so I can teach you how you can upload actual files from your phone to app rights storage buckets and then getting URLs for those files so you can put them within your aight database and then see the video you have posted on your homepage first things first we can open up a model that allows ows us to pick either an image for a thumbnail or a video so let's say const result to extract the image or video we choose and say await document picker like this and this document picker will come from Expo document picker which is another package we can install so right here in the terminal we can clear our second one and say mpm install Expo D document ment Das picker and press enter once we install it right at the top we can say import everything as document picker coming from Expo document picker now to that document picker we can use a method called get document async to which we need to pass options object of type and here we need to Define the type that we want to get now in our case the type will depend on which input we click on video or thumbnail so we'll say if select type is triple equal to image then the types will be an array of image PNG as well as image JPEG and else the type will be a video MP4 as well as a video GIF and now if you save it and if you click on upload video you can see that it will actually open up your recent videos we can also give it a shot with a thumbnail and here you can see some icons that I recently downloaded to customize my iPhone you can also go to browse and see all the different files on your phone in this case just sticking with recents is fine but now that we select a specific image we want to do something within it first we have to make sure that our user hasn't cancelled so we can say if not result. canell in that case we can set state to either thumbnail or video by saying if select type is triple equal to image in that case we can set form we can spread the entire form and update the thumbnail to be result do assets Z like this and we can also duplicate that if right below and say if select type is video then we can update this video right here to results. assets zero else not else to these ifs but to this outside if if we have cancelled the submission then we can just set a timeout where we have a callback function and we can Define the delay of like 100 milliseconds and we can show an alert coming from react native. alert document picked and json. stringify the result we don't want to replace anything so we can give it null and the space will be two this should nicely show us which file we have selected so let's give it a go I'm going to click upload video and I'm going to select this real and as you can see it automatically got it here we also got document picked assets now cancel to true so this is only if you cancel out but in this case we actually have the asset here the only problem is once I try to play it then it opens up this form once again we'll work on that later on for now let's also select a thumbnail I'm going to go with this nice thumbnail image right here and now that we can select those files the only thing we're doing in this open picker is we're setting them to the state so now we have to actually create the submit function that will upload them to our database so before we submit we have to ensure we have all the data so we can say if there is no form. prompt or if there is no form. tile or if there is no form. thumbnail or if there's no form. video if any of these is false or empty then we want to return an alert do alert that says please fill in all the fields if we get past this if then we can say set uploading to be true and we can open up a try and catch block it will also have a finally Clause right here where we can reset our entire form so we can say set form and we can basically reset it to the starting state by copying the empty values and pasting them here and right below we can also set uploading to false because we are done with uploading so now if we have an error we can simply alert alert error with an error message right here and how will we actually upload this file well first Let's do an alert. alert where we can say success and post uploaded successfully then let's also navigate to the homepage by using the router functionality by importing router from Expo router and then we can say something like router. push pointing to home so we can see our newly uploaded post and then the most important thing is right here we have to make a call to aite to add this post to our database so let's navigate over to aite and let's create a new function export const create video and it will be equal to an async function that accepts the entire form data as the first pram we can open up a try and catch block and in the catch simply throw a new error where we pass the error and in the try we can first upload our video and thumbnail and then once we have their URLs we can simply create a new document in our database so let's do just that I'm going to say const and I will destructure the thumbnail URL and video URL which will come from the call of await promise. all because we don't need to do one of these one after another we can at the same time start uploading both files and we can do that using promise. all then we can pass an array of calls we want to do and here we can call a new special function called upload file to which we can pass our form. thumbnail with the second prop of image and we can duplicate that and pass the form. video with a second prop as video as well and let's separate these by commas there we go now of course this upload file is another function which we have to create so let's create it just about export const upload file is equal to an async function where we can get the file and the type of that file and we can upload it to app rights storage buckets first things first we can check if a file even exists so if there's no file we simply exit out of the function then we want to get some data or information out of the file by saying const and we can extract a mime type and then spread out the rest of the properties coming from the file we can do that like this and then we want to reconstruct that file because that's how aite accepts them we can say const asset is equal to an object with a type equal to MIM type and we can spread the rest there we go so basically what we have done is we have taken everything out of the file and just renamed the Mind type to type as that will help app understand what file we're talking about then we can open up a new try and catch Block in the catch we can throw a new error as we typically do so we can copy this entire thing and paste it here and in the try we can say const uploaded file is equal to await we call the storage for the first time right here so we have to initialize a new storage bucket right at the top so let's do it here account avatars databases but now we're also working with storage which is new storage coming from aight of course at the top so let's go ahead and import it there we go let's go down and then we can say something like storage. create file and we have to pass a couple of things into it first we pass the storage ID then we have to pass the id. unique as we want to give it a unique ID to this file and then we pass the actual asset into it so that's going to look something like this and then arite will give you a file URL so we can do something like const file URL is equal to await get file preview to which we have to pass the uploaded file do dollar sign ID and then the type as the second parameter and we can return that file URL and the only thing that's important here is that this get file preview is a bit different for our video and audio file so let's turn that into a new function right here export const get file preview which is equal to an async function that accepts a file ID and type we can declare a file URL at the top let file URL and open up a try and catch Block in the catch we can simply consol log or throw a new error and in the try we can check if we're working with a type is triple equal to video or else if we're working with a type triple equal to image and based off of that response we're going to get the file URL a bit differently so if it is a video we can say file URL is equal to storage. getet file view to which we pass the storage ID as well as the file ID where we want to get it from now to get the file URL off of an image we can say file URL is equal to storage. get file preview a bit different not get file view and here we can pass the storage ID as well as the file ID so that's the same but now we can pass the width which is going to be 2,000 the height which is going to be 2,000 and the gravity which is going to be top and finally quality which will be 100 so we can basically pass a few more pieces of information to get the right preview and the right size finally we can also do an else and throw a new error of invalid file type it in case we don't get video or image and finally if there is no file URL that we get back we can throw an error one more time and if everything succeeds we can basically return this file URL great so now we have the get file preview which is used in the upload file which is used within create video which then returns us the thumbnail URL and the video URL which we call both at the same time time as we can upload both at the same times they don't depend one on another so they can happen at the same time so once we have those URLs we can say const new post is equal to await databases. create document here we need to pass the database ID within which we want to create that document and a video collection ID which is the ID of the collection where that document belongs and then the id. unique which will give it a unique ID and the last thing we have to pass is an object of the actual data that we want to create so it will be a title coming from form. tile then we want to give it a thumbnail equal to thumbnail URL after that we can pass video as video URL prompt equal to form. prompt and finally creator equal to form. user ID and with that we have everything we need to create a new post so finally once it actually gets created and added to the database let's just return it right here to our front end great so now we have a function called create video which uses upload file which uses get file preview which we can use within our create form so right here let's await and for that we have to turn our submit into an async function and why are we awaiting well we're waiting create video which we have to import of course from aite so let's do that going up we can import create video from slash SL lib aight let's just command click it or control click it to see if we're pointing to it in the right way we are and we're creating the video and to it we have to pass a couple of things I'm going to spread the entire form and I'm going to also pass the user ID equal to user. dollar sign ID that way we have all the necessary information to create a post so let's give it a go I will first upload a video I'm going to go with this Instagram real we can also give it a title of I G real I'm going to post a thumbnail image let's go with this one right here and let's enter an AI prompt I'm going to say something like testing and press enter let me spell it properly testing there we go and I'll press submit and publish it gives us property user does not exist that's okay at least we got an error in this case we cannot get this user because we have never imported it so right at the top we know how to do that we can simply say const d structure the user which is equal to the use Global context which is a custom context hook so we can import it by saying import use Global context coming from. context SLG Global provider now we have access to the user and we can give it another go before we test it out there's one more thing I want to fix right here we have this else that sometimes throws this annoying alert and I think we can safely get rid of it nothing bad will happen we just won't see the alert on the screen so we can hide that and another little tweak that we can do is within this touchable opacity we cannot actually play the video or in interact with the native controls because it's within the file upload button so let's simply remove the use native controls and is looping that way we'll know the video is there but we won't be able to interact with it so let's give it a shot I'm going to name my video something like IG G real I'm going to upload the video right here we can see that it is uploaded and now you can choose and you can add another one or you can just exit out of it we can choose a thumbnail for that video I'm going to go with this background and the AI prompt is let's say something like testing I think that should be good there we go and let me click submit and publish we got an upright exception file extension not allowed but why is it not allowed that is one of the most basic file formats so let's see where do we disect allow people from updating that file extension I think here on the file picker first of all we can also allow people to select image and then we can do SL JPEG and we can also go back to aite and within here we can go to storage files settings scroll down and we can add JPEG and press enter and click update this should allow us to add add this file extension and you can also select others if you want to going back to the code we can give our create one more chance let's go to create let's once again type something like IG real let's upload a video I'm going to go with this one and upload a thumbnail and select a prompt once again I'm going to do test and press enter this time we get the file you're trying to upload is above the limit allowed for your plan okay so the limit is about 50 megabytes for the free plan so let's try to find something a bit smaller and while we're doing that I just noticed one more thing as well if I click here you can see that it actually opens up my files as we're using a document picker and I thought this might be a bit more fitting for videos but still videos images you want to get them from your G right so let's use something like Expo image picker instead of a document picker the installation is simple MPX Expo install Expo image picker so back in our terminal MPX Expo install Expo image picker and the usage will be very similar to what we have with a document picker we basically imported and we use it as we normally would but the method is launch image library and then here we can choose which types of media we want to get so let's go ahead and copy their example go back here and instead of using this we can simply override what we have and let's not forget to import image picker right at the top by saying import image picker from Expo image picker let's see if we have to import anything else no I think that's basically it and and let's see media types image picker. mediatype options. all we don't want to go for all we want to choose a specific type so let's say media types if select type is a string of image then we'll do image picker media type options dot I think it's photos or maybe images yeah it's images you can see only images else we can do something like image. medat type options do videos no I don't see it that it autofills it so we have to make sure that this indeed is the right property to choose if select type is triple equal to image then images else media type options dot let's see I don't see that it autofills anything so let's go back to the docs or even better we can command click right here and see what we can get all videos images okay it's as simple as that for some reason Visual Studio code didn't autofill it for me but it's videos we are not going to allow editing I don't think it's needed and we can leave the aspect ratio and quality as they are and let's give it a shot I'm going to click upload and I got an error and now I can see why it wasn't autofilling videos I forgot to add the dot image picker instead of image at the start so now it recognizes only videos this is great let's save it and let's give it one more shot and you can choose any of your videos under 50 megabytes you might want to do some compression online I have selected one right here and I'm going to upload it this video was AI generated and it looks like Japan so I'm going to say Japan right here and I'm going to also upload a thumbnail there we go I have uploaded a thumbnail and we can say something like Japan in Spring let's say that is the AI prompt that we gave it finally let's click submit and publish and hope for the best this time we got another error at least you can see it on my screen here it says canot Trade property of dollar sign ID of undefined so let's search for dollar sign sign ID right here and we have only one belonging to the user right here and we are getting the user from our state so I don't think it's this ID this one should actually exist but it also could be some of the IDS coming from aite here if I expand create video we can search for dollar sign ID and you can see that it could be the new account. ID this is in create user rather rather we want to look into create video here we have nowhere dollar ID what about an upload file here we have it uploaded file dollar sign do dollar sign ID and do we have any in file preview I don't think so so I think it's pointing to this one right here so as we know that this dollar ID could be the problem the problem is with uploading a file and that could be because we switched from document picker to to image picker so this modification we're doing with the assets and the M type might not be needed so just to be safe let's do a conso log where we can conso log the file to see what we're getting back and we can also conso loog the uploaded file to see how that looks like and let me just say uploaded in a string right here just so we can know what this is relating to and in the above one I'm just going to Simply say file just so we can easily find it in our terminal I'm going to save it and now we have to try to upload one more time and I will speed this process up for you there we go we know that it won't work again but at least we can see the logs so let's click submit and publish and it looks like the uploaded is undefined but the file above actually has its asset ID but let's see if it has the mime type it does have the the type and it also has the M type which is great so in this case I don't think we even need to transform it manually as both have their own MIM types so let me just reload our terminal and start it one more time so what we have to do now is ensure that we pass the asset in the exact right format that aight accepts it in and it's name type size URI so let's quickly copy this and let's start forming this assd from scratch that way you'll even better understand why we were doing what we were doing right here first of all all of these are strings and size is a number like this we have to add commas and we have to understand where we get all of those values from but at least that is now noticeable we know because we have conso log the actual file so let's search for IT thing by thing for first of all we have file size which is size right here so we can say size is file do file size one down three more to go URI let's see if we have that here we have it there we go U so we can say U is file. U then we have the type in this case the type is the m type so so let's say type is file. mim type and finally we have the name the name is the file name so let's say file. file name great now we're forming the asset in the format that aite should gladly accept it in let's remove those consoles and let me swipe back up from my settings to our app let's reload it one more time just to be sure and let's create I'm going to speed up this process for you one more time there we go and I will press submit and publish post uploaded successfully that is great now if we swipe up to reload right at the bottom you'll see a new video that we just uploaded and what do you say that we show it on top so let's go to get all posts and like we have done with get latest posts simply copy this query and add it right here below Video Collection ID and remove the limit since here we want to get all the posts so we're essentially sorting it by a descending order that way our new post will appear right on top JS Mastery posted Japan we can click on it and we can see the video that I just posted if you want to you can also turn your phone around and see it in full quality believe it or not this video was created by AI so with that in mind everything is working perfectly we can see all of our other videos as well and play through them and after some time this video gets back to a thumbnail in case you want to replay it one more time so with that in mind we have successfully created the create video form we have had two different file uploads or should I call them image uploads because we're picking directly from the Gallery both videos and images we're creating those files uploading them to a storage bucket retrieving their URLs and finally creating a new document within our app right database we also have our profile and you can see immediately that we get this new Post in Japan coming directly to our profile if you want to you can also modify the order in descending within get user posts right here that way it will will also appear on top then you can add a comma and this time without an array simply saying query. or your descending within the same array right here we're going to sort it and if you go back to home or back to profile you should be able to see Japan appear on top so now we have successfully created our onboarding login and register screens as well as homepage with two different types of posts horizontal view as well as a vertical view a search page page where we can search for different things as well as a profile page and a create page and with that in mind you can see that three out of four of our screens at the bottom bar have been implemented home create and profile but bookmark is still empty and that's for a reason going back to our design you can see this saved screen which is almost exactly the same as search so I invite you to implement this page on your own it will require a small bit of almost everything that we worked on in this video it will require you to first of all add a heart icon within each one of these posts within the homepage then once you click on that heart it should make an ight update request to add the users's ID that like that post to somehow Mark the post as liked by that specific user for that you might want to go to databases to videos and then there you might need to add additional attributes such as liked and that will be a relation to users so it can be an array of user IDs that have like that post once you have that going you can make a new fetch that fetches all of the liked posts by the current user and then you can develop this screen called saved videos where you can show the videos that you fetch it's not simple but you can do it if you want to have some more practice and if you don't want to do it one thing you can do is just search for bookmark that's going to be right here within the layout and we might want to remove or hide this tabs screen as it's currently not functional so if you do it this way you can still see this triangle at the bottom right so to get rid of that we can just remove this bookmark route as it automatically picks it out so if you remove it and reload you can see that now it is gone and you have three fully functional apps leaving you with a fully functional react native application that is full stack amazing jab if this is your first react native application you have ever coded well huge props to you for coming to the end of this video and building it out and learning a lot about what react native and Expo have to offer and if this is not your first react native app but you still came to the end congrats you learned how to create a full stack application learned a lot about the latest and greatest of what Expo and react native have to offer with file based routing Expo AV package for audio video image and video uploads and making the app full stack with aight if we were on the web now we would deploy the app very quickly and easily but the native mobile application game is a bit different we have to deploy our applications to their respective stores to Google Play Store if you're on Android and to Apple Store if you're an iOS and for that we have to build out our native source code create an account on one of these platforms and get our app out there if you're interested in learning how to deploy your applications to App Stores let me know down in the comments and download our react native guide that I mentioned at the start that way once we do release a video or a course on that topic I will let you know via email once again thank you so much for coming to the end of this video and building this app with me but you should be thinking to yourself actually because you have invested your time into improving your skills and that's what matters the most so once again great job and I'll see you in the next one have a wonderful day have you ever spent hours waiting for your doctor's appointment those days are gone because in this course you'll learn how to build and deploy care pools a healthcare management system with realtime SMS notifications designed to streamline the tedious checkup process you'll solve a real problem so don't forget to mention that in a job interview with authentication registration for filling out personal information medical history and identification easy appointment scheduling with your preferred doctor confirmation screen upon successful booking model for granting access permissions and a comprehensive admin panel for scheduling or cancelling appointments of any kind with SMS notifications all of this while learning nextjs with serers side rendering nested layouts server actions and revalidation advanced and reusable form management with unique components like date Pickers Country phone input and OTP verification using typescript react hook form and Zod Shaden and tailn CSS for a modern completely mobile responsive UI the latest open- Source apped features including file storage and SMS notifications with willo and Sentry a monitoring software for analyzing performance and tracing requests now with even better feat methods where you'll get an open-source codebase you can look at if you get stuck a custom figma design so you know exactly what you're building and a Discord server to get all your bugs resolved all those things are free so grab them from links below while I continue telling you about all the other great stuff oh and all the software we'll use in this course like appid shaten and century is free too with no credit card required so that you can follow along with the entire course from anywhere in the world a basic to medium understanding of react or nextjs is needed so if you're not there yet check out our nextjs crash course and come right back by the end of this course you'll feel confident enough to build any complex forms and let's be honest every app needs proper forms and realtime SMS notifications and here's a demo to show you precisely what you'll build first you'll develop a welcome page that lets your users sign in using their phone numbers you can choose a country which automatically fills in its country code and then type the number and because this is my first time visiting this page I'll be redirected to the registration page where I'll need to register as a patient there is a ton of info to fill out including General details like name email phone number date of birth and more and your users also must provide medical information such as their primary care physician allergies current medications and all relevant medical history additionally they'll need to provide identification including the type and number of their ID along with a scanned copy of the document which you'll allow them to upload finally they review it and consent to the Privacy terms whoa that's a lot of info but you won't be cutting any Corners here here this is a real Healthcare application after all once they've successfully registered they'll be redirected to the appointments page to schedule a new appointment here they can specify the doctor they want select the date and provide the reasons for the appointment along with any comments then a successful notification will appear leading us to the final confirmation page it shows that we've successfully requested an appointment to meet with a doctor and we'll receive a confirmation SMS from them soon we can also schedule a new appointment but let's put that to the side for now and explore the admin side of things back on the homepage you'll notice a small link on the bottom right clicking it will open up a model where you must enter the pass key 6 ons in my case to access the admin page and there you have it we're redirected to the admin page where we find a wealth of health information including stat cards display the total number of scheduled pending and canceled appointments we also have a data table displaying the list of these appointments information about who request to them and two actions available for admins to take if everything checks out with a patient the admin can schedule or confirm the appointment with the designated doctor triggering a confirmation SMS to be sent to the patient let me schedule it and show you on my phone there it is a new SMS confirming that my appointment has been scheduled great I won't have to wait in line anymore the admin can also cancel the appointment but they must provide a valid reason the entire table includes proper pation and it is fully responsive in fact the entire application is designed to work seamlessly on all devices so are you excited to build this app maybe extend it further and sell it to your local hospitals so you don't have to wait in cues anymore or just use it as an example of a real world problem you've experienced and decided to solve with your programming skills trust me recruiters and hiring managers love that I'm super excited to dive into the code with you so let's not waste any more time and start coding to get started developing our great Healthcare application we can create a new empty folder on our desktop and callid Care pools which is the code name of our application then simply drag and drop it into your Visual Studio code and let's get started first I will open up the terminal so that we can properly initialize our project and we'll initialize it using only the latest and greatest Technologies we'll use react for creating web user interfaces we'll of course use njs to power up that react and make it super high quality and efficient we'll also use tailin CSS to rapidly style our applications and chaten to get some amazing components right out of the box that allow us to then further style them we'll also use aite an open-source tool that allows us to add databases storage and also SMS messaging to our application and don't forget that we'll make this app Enterprise ready by implementing Sentry an application monitoring tool considered not bad by 4 million developers and as I mentioned at the start of this course you can get a complete figma design that you can then follow along with this will give you access to all of the pages including the onboarding all the models like the OTP verification forms and everything so you can use this to build this entire app entirely on your own if you want to or as additional help to following along with me so you know exactly what you're building and how we can transfer all of the other designs into code so you can get it now from the link down in the description but with that said let's go ahead and initialize our next GS application by simply copying this command going back to the code and running MPX create next app latest and then do slash which will create it in its current repository so let's press enter to initialize it it's going to ask us a couple of questions we will use typescript es lent Tailwind CSS no Source directory yes to the app router no need to customize the import alias basically just press enter for all of the options let's wait until it gets initialized and then we can take a look at the starter codebase there we go it has been initialized and what we have here is a typical nextjs application where we have a page layout some CSS and a favicon so let's immediately clean it up a bit by going to the page and removing this entire main tag and the return statement what we need instead is just return and we can return a div that will render an H1 that will say something like home great we don't need anything else and we can also go into the layout and modify the metadata we'll call it care pools a healthcare management system while we're here we can also go into the global. CSS and remove everything besides these three Tailwind utilities that allow us to use Tailwind classes so just to test whether Tailwind is working back on home we can give this H1 a class name equal to and let's do text- 3XL to make it very large and we can also give it underline we can also remove this existing favicon as soon we'll completely customize it with our own carep one great so now that we've done a couple of changes let's go ahead and run mpm run Dev to check out our app in the browser back Local Host we can see a big underlined home which means that we are good to start developing it so let's start with a layout as that wraps our entire application we won't be using the inter font rather we'll use the plus Jakarta Sans coming from next fonts Google so we can just exchange it here and call it font Sans and we can apply additional options so we get more different weights such as weight is an array of let's do 300 400 500 600 and 700 and that's just going to be weight and all of these I believe have to be strengths so just wrap them in quotation marks also we can assign a variable to be-- font Das s so whenever we apply this this font will be used so let's scroll down and let's give some additional class name to this body we'll use a CN which is short for class name and this allows you to add both static and dynamically rendered class names let me show you how that works we have to import CN from at SL lib SL utils and typically this is installed for us as soon as we install Tailwind for some reason it didn't get added here but no worries we can just create a new folder called lib and within it we can create a new utils dots file and inside of here we can put some utility functions we'll use later on within our code I actually prepared some of these for you within the finished GitHub repo this is not finished code but if you scroll down you can see Snippets code to copy number five so go to the link down below go to Snippets and then here you can find some of the files which are needed for this project one of which is lib U.S so simply expand it copy it and paste it right here for that we'll have to install clsx and Tailwind merge which are some of the Tailwind utilities so let's open up a new terminal and run mpm install clsx as well as Tailwind Das merge and very soon the squiggly lines should be gone great now if we go go back to the layout and if we try to import CN one more time from add slash lib for/ utils you can see that it properly gets it and now we can call it as a function and I can show you how we can use it first you pass it some classes you would always want to call such as Minh screen in this case to give it a Min height of 100 VH meaning our homepage will take the full screen BG dark of 300 which will be the background color font Das Sans which means that this font will be applied all over the pages and anti alast this is something that helps make some fonts look a bit better and then you can apply an additional property which is dynamic font sense. variable in this case we're letting it know that we'll be using this variable when we want to indicate the use of font s you'll also notice that we have something known as BG dark 300 here which is some kind of a dark color but it really hasn't been specified anywhere neither in the global. CSS nor in the Tailwind doc config.sys CSS which will contain some base Tailwind classes that we can use so simply copy it and paste it right here in global. CSS and then copy the Tailwind doc config .ts and override the existing tailin CSS config you'll notice that here we have this dark 300 there we go which is a shade of a dark color we'll use for the background basically whenever you want to have some custom UI you never want to repeat yourself with these specific strings because it's easy to make a mistake so what you do is you extend the colors of the tabling config and that way you have all of the variants you want to use and back when you use them it will automatically know what kind of color this is back into tailin CSS config you can notice that we're also using this Stalin CSS animate for some of the properties as a plug-in so we can simply install it by running mpm install tailin CSS animate great moving back to our browser it seems like there's nothing there but there should be this home there it's just that now the dark background is being applied so going back back to our page we can now give this a text- white property and our home is visible again so now that we have Tailwind up and running we also want to make sure that shaten works too and shaten is a component Library we'll use so go to ui. shen.com and click get started go to installation choose nextjs and let's just follow the Second Step which is MPX chatsi and UI latest in it open up the terminal and paste it it'll ask you a couple of questions just press enter to all of them then it asks us to add the font which we have already done and it asks us to extend the theme in tailin config which we have already done as well and that's it we can add our first component MPX chaten UI latest ad button so we can add a button and this is a pretty cool thing about chaten it doesn't install the entire Library only when you specify which component you want to use it adds it to your code base great so now we have a button and how do we use it well we just import it and call it so let's do just that I will say button right here coming from components UI button and I will say something like click me also you can notice that tail over Road our .ts so simply press control or command Z to go back one step to get our full file or copy it again from the GitHub repo down below once we have that we can go ahead and check this out in the browser and you can see that everything is white once again so going back to Global CSS you can do the same thing as we've done with the utils and that's because global. CSS also got overridden by shaten so simply copy this one more time and paste it right here and let's also check the tailin config it looks like it over rrow these colors as well so simply press contrl Z or command Z to get one step back and to get all of our great extended colors and we're back on the homepage but as you can see now this click me button is dark and the background is dark as well we want to find a way to let chatsi and know that we want all of the components to be automatically in dark mode because our entire app app is in dark mode so how can we make that happen well if you go to shaten and click dark mode right here and choose nextjs it will tell you to install next themes so let's do that paste it right here npm install next themes and we can create a new component called theme provider so let's do that right here it should be other components theme- provider. SX and paste what you copied next we have to wrap our app in the layout with the theme provider so let's copy this part right here go back to the layout and wrap our children with it of course make sure to import it from components theme provider and in this case we'll give it an attribute of class the default theme of dark and we don't need anything else this is it as we'll only stay on the dark mode great so now we have the body wrapping this and everything looks great as soon as we do that the button text will be clickable as well which is exactly what we want so now that we've laid out the foundations with shaten Tailwind CSS and general styling we are ready to start building up our homepage to get started with our homepage we can give this div a class name equal to flex to make it a flex container h- screen to give it full height and Max dh- screen to also set its Max height to 100 VH right within it we'll want to display another section and this section won't have a scroll bar so we can give it a class name that's going to say remove dash scroll bar set it as a container and give it a margin y of Auto now these two classes are not coming directly from Tailwind rather they're coming from a global. CSS so if you want to learn more about what a specific class does simply hover over it and you can see that it will apply some widths margins and paddings or search for it and you'll be able to find it right within the globals or within the tail config great so now now that we have this section right within it we can have another div that will have a class name equal to sub- container and a Max W so max width of I found the value of 496 pixels to work the best and within it we can display an image this image will of course be imported from next image so we can get all of the image optimization things out of the box given to us by nextjs and here we can render our logo but we don't yet have access to it like we don't know how our logo will look like so going back to our design this thing right here is what we're developing right now a left sidebar with a form and the Right image right here so we need this care pulse logo how are we going to get it well you can keep selecting it until you get to the logo Mark and then you can just exported right here and sure that's simple enough right you just download it and that's it but just so we don't have to download every single image right here I have already exported all the illustrations icons and more from this figma design so you can get them all in one package you can find them within this GitHub readme if you go below the Snippets onto the assets click here and simply download them from Google Drive it might tell you that it cannot scan them as there's some viruses but don't worry about that I'm not trying to hack you I just want to give you the actual icons so once you download them simply unzip them remove the existing public folder and then drag and drop the new public folder right to the root of the directory and say copy folder and you'll be able to see a public folder with all the assets great if you have that we can give this image a source equal to SL assets slash icons SL logo.svg we can also give it a height of about 1,000 a width of about 1,000 as well and we can give it an ALT equal to patient and a class name equal to margin bottom of 12 h of 10 and w- fit and we can save it finally if you go back to Local Host 3000 you should be able to see something that looks like this pretty simple so far I know but soon we'll add an entire patient form right here so let's actually go below the image and let's create that component which will soon become our form we can go to the components folder create a new folder called forms and within it we can create a new file called patient form. TSX in there you can run rce which will create a basic react Arrow function that looks like this allowing you to Simply import it right here by saying patient form coming from components forms patient form going back you can see a simple text that says patient form which will update soon for now we can do the rest of the homepage by creating a new div below the patient form and this div will have a class name equal to text -4- regular and for now we can simply give it a copyright sign I typically just Google that so copyright sign copy it's going to be this symbol right here copy it and paste it here yep that's the one 2024 care pulse and you should be able to see it here let's style it better by giving it a margin top of 20 Flex justify Dash between and we can actually put this within a P tag so copy it paste it within a P tag and give it a class name equal to justify items end text- dark- 600 and on extra large devices text Dash left below this P tag we can have a link component which we can import from next link it will render a text that says admin and it will have an hre pointing to for slash question mark admin is equal to True with a class name of text- green- 500 to indicate that it is clickable and finally after we exit this entire section we can render our big image this will be a self-closing image with a source equal to SL assets slash images SL onboarding Das img.png and we can give it a height of 1,000 width of 1,000 an ALT tag equal to Patient class name equal to side- IMG and a Max W of 50% so it takes 50% % of the screen if you do this you'll be able to see something that looks like this we have a great welcoming doctor on the right side indicating that we can trust them with our information so what do you say that we focus on creating this patient form next we can go back to the homepage and believe it or not the homepage is completely done the only thing we'll add later on is the OTP verification so I can add a comment right here to do and we'll make it OTP verification also known as the pass key model what I'm referring to is this thing right here where if we want to join the admin panel we're going to have this verification but more on that later as for now we'll be focusing on the patient form so let's navigate over to the patient form to start working on the patient form we have to set up our forms in general so you can think of this lesson as a master class and creating complex and reusable forms we'll be using shaten and they outed the Box leverage react hook form and Zod and they say themselves forms are tricky one of the most common things you'll build in a web application but also one of the most complex at least if you want to do them well they have to be well structured and sematic correct easy to use and navigate using the keyboard accessible have support for both sides of validations and they have to be well styled and consistent with the rest of the application so let's see how we can build a form using react hook form Zod and Shaden form field what we'll do is we'll move over to the installation part so let's copy this part right here and let's install a shaten form immediately after that we'll need to create a form schema so let's copy this part right here and add it to the top of our application first since we're using forms we'll have to have some browser keyboard interaction and some events which have to be fired which means that we have to make our application run on the client side we're importing Z from Zod and Zod is used for validation so here we can Define the schema of our form next we need to define the form itself so let's copy everything from here let's copy it all the way without the last curly brace all the way to the top and let's just override everything right here including the patient form and we'll just have to rename the profile form back to the patient form and we'll have to properly export it by saying const patient form is equal to an arrow function and we're exporting it at the bottom so what what we have done now is we have imported the Zod resolvers and use form from react hook form which allows us to Define our form so we're defining our form right here at the top and we're saying that this form will be of a type form schema which right now contains only a username of minimum two characters and you can even provide additional messages for validation next we Define an onsubmit Handler where you render some logic that happens once the user submits the form and finally we have the UI so going back right here we can actually build our form using the form component so we have to copy all of the Imports and paste them right at the top we have already installed a Shaden button and a form but now we have to also install an input so we can simply say MPX chat CN UI latest add input and now the that we have the Imports we can also just copy the actual form usage so let's take it and let's replace this div with the form we just copied and of course we can properly indent it and that's it we're done our form should look something like this so let's check it out hey that looks great we have the username shatan right here this is your public display name and we can actually type something and it looks good we also have a button to submit it and the button has complete validation so it says username must be at least two characters and it won't let us pass if we don't add at least two so there you have it this is your simple form but now let's extend this even further let's first do some basic styling by giving it a space- y of six and a flex of one and within the form let's also render an additional section that will have a class name equal to margin bottom of 12 and space y of four and here we can render an H1 that will simply say hi there and we can also render an emoji maybe just a wave you can just copy this from Google and we can render a P tag there saying something like schedule your first appointment let's style it a bit by giving this H1 a class name equal to header and we can also give this P tag a class name equal to text- dark d700 going back this looks much better and after that we immediately have our form field but now if you wanted to have more form Fields like in our application where we'll have hundreds of them you would easily surpass couple hundred lines of code which is a lot so what you want to do in this case is copy this form field and turn it into a custom reusable form field component so let's do just that I have copied it and I will create a new component called custom form field. TSX and you can run rafc right here and instead of this div we can paste our custom form field let's also make sure to indented properly and let's not forget to get all of the imports from the patient form into our new custom form field so I will leave just the form right here and all of the other ones will be moved to the custom form field right at the top don't forget this one will also have to be turned into a use client component and as you can see we're also missing some additional things like the input which we can also import right here from components input so let's just take it from here and paste it here and the next thing is this form and don't forget the form resides in the actual patient form component it is this form right here where we have defined it for the first time so now we have to figure out a way of how we can pass that form as a prop over to the custom form field well we can do that easily let's go right here and let's render our custom form field imported from do/ custom form field and to it we can pass the control which is equal to form. control so now if we go back right here we can accept a prop so that will be props of a type custom props and we can define those custom props right here as an interface so interface custom props will have a control of a type control coming from react hook form of a type any and now we can replace the form control with just control coming from props but of course we have to destructure it right here so let's destructure the control and as you can see we're all good now we still haven't made this a fully reusable component do you know why well it's because this is just one single form field we could have just used it here as well right the reusability happens when once you allow this component to change and to morph to different use cases and how I approach this is you take a look at the things that should be the same for every single form input like we have this form field and if you duplicate it two times which are the lines which will be the same and which are the lines which will change well of course the name will change as it will be different for every single input the label will change too maybe even the type of the input will change and the description will surely change too so let's pass those as props first of all let's define the field type and of course you could just say text or input which is totally fine but we can go a step further here and make it something known as an enum so let's scroll to the top of this component and let's say export enum form field types or just type is equal to an object and here we can say input is equal to a string of input so now we know that this form field type will be form field type. input like this and if we go back into the custom form field we can now accept the form field type or we just called it field type I believe and we can Define it right here here as field type is form field type coming from forms patient form so this now ensures that it can only be of one of the types we have specified above we could have just simply put a string of input right here but with those types of strings it's very easy to make a mistake and say something like in for example and then it will be very hard to notice a mistake here because if it were a string it wouldn't throw an error but now it says Hey input is not assignable to form field type most likely it should have been an input so you just do it like this and then if you make a mistake here it's quite obvious right this doesn't exist and you get an immediate error cool so now you learned about enums which is also very good thing to know about what else did we say we want to pass to this thing well let's pass pass a name equal to name let's pass a label equal to full name let's also pass a dynamic placeholder equal to John Doe maybe some inputs will also have an icon Source equal to SL assets SL ions SL user. SVG and we can also pass an icon alt which will be equal to user so all of these things will be different for every single input and now that we're passing them we can just go into here we can accept it and then just use it let me show you how the field type will be used to render different kinds of inputs or Fields but name is very simple so let's look into that first we can use the name and then instead of using a default username which is always the same now each one of our form Fields can have a unique name and also we don't want every single one of our form fields to have the same layout this layout will be used for an input but sometimes we maybe want to render something else so I will delete this entire thing and say form item give it a class name equal to flex das1 and here we can check if field type is not equal to form field type. checkbox this is also one of the types we'll have in the future and if a label exists then we want to render a form label that's going to look something like this and inside of there we can render the actual label so now it's letting us know that the checkbox is not a valid type under form field types so let's go ahead and add it we can have a text area which will be equal to a string of text area we can also have a phone input which will be phone uncore input is equal to phone let's do phone input like this we can also have a checkbox equal to checkbox later on we'll have date Pickers too so date picker is equal to date picker select is equal to select and a skeleton input is equal to a skeleton so these are all the different types of form fields and make sure to add commas at the end of each one of these great so now going back doesn't complain about the checkbox anymore and the label as we know is coming right from props so we can get it right here also our custom props are complaining about the fact that we're not accepting these types of props so let's define that as well alongside the field type we also have a name of a type string we have a label which will be optional of a type string a placeholder which will be optional of a type string and I can Source optional of a type string an icon alt optional of a type string disabled property also optional of a type Boolean date format also optional as it will only be shown in inputs containing a date so calendar inputs of a typ string show time select to further modify the calendar inputs whether we want to show time or not of a type Boolean children because sometimes we want to show something inside of an input of a type react. react node we also have a render skeleton which will be a function accepting a field and returning a react node this is typically used when you want to show a loading state for an input and I think that will be enough for now so now it's not complaining about the props we're passing and it's getting the label right here and we're missing an and sign here as well so if the field type is not a checkbox and if a label exists then show the label next we can create a new functional component that will render all different kinds of inputs const render input is equal to a functional component that returns those inputs for now let's make it return a single input like this we can just pass the type text and the placeholder that's good enough for now and we can render this render input right here to it we'll pass the field equal to field so we know what kind of field we want to render so maybe render field will be a better name let's rename it render field because input is only one type of fields that there are and we can also pass all the other props we're passing into the custom form field by doing it like this so this means that we cannot these structure these properties right here at the top we have to leave the props exposed but we can destructure them right here const and then get this out of the props this allows us to destructure them but also pass the entire props object right here as well now we can also let tab script know what the render field will be accepting it'll be getting a field as well as props and this will be of a type field is of a type any and props is of a type custom props there we go and then just at the bottom we can render a form message to which we can just pass a class name equal to Shad Das error so you can see how we're making this component much more reusable it changes the name it changes whether it shows the label or not the form message and also we can render different kinds of fields depending on the form field type so going back to the code you can see that we now have a full name and we still have an input so let's collaps this custom form field and let's actually focus on this render field because this is where we can customize this form field further let me show you how instead of always rendering an input we will just return a switch case so we can see switch and switch typically takes a key it will be of a props do field type and a value which can be form field type do input like this so only if the form field type is an input then we can return something let me show you what we can return a div that will have a class name equal to flex rounded DMD border border d-500 and BG dark 400 so now we're creating the layout around the actual input you can see how that will look like next only if props that icon Source exists then we want to render the actual icon so we can render an image of course this would be a nextjs image we can give it a source equal to props do ion source and just so we don't have to say props this and props that we can destructure the props further right here by saying const and then destructure the field type from profs we can also destructure the icon Source we can also get the icon alt we can get the placeholder I think there's many more things which we'll be able to get later on especially as we dive into some more detailed form fields for dates and so on but this is good enough for now so now we can remove this props that field type it's just field type and also if an icon Source exists render an image with an icon Source equal to this we can also give it a height equal to 24 a width equal to 24 an ALT tag equal to Icon alt or just icon if it doesn't exist and we can give it a class name equal to margin left of two just to divide it a bit from the left then below this icon Source we can render an actual form control inside of which we'll put a self-closing input tag with a placeholder equal to placeholder we can destructure everything else from this field that we're passing into it and give it a class name equal to Shad input and border -0 and this is our input so if we go back now you can see how great this input looks like and since we have given it a name property it automatically recognizes it and fills it using my password provider and I understand how this can seem like a lot of extra work that we're doing right now but trust me you'll appreciate it so much once you'll start creating all of this inputs here because you'll just be able to reuse all the great work you've done and instead of doing it in five or 600 lines of code you'll be able to do it in just a couple so let's collapse this case of input and whenever we need to further modify this render field to add another type we can easily do that by adding another case so let's see which other fields we need to add to our initial form that will be an email address and a phone number let's see how that works going back to our patient form the only thing we have to do right now is duplicate this custom form field and change some properties it will also be of a type input name will be email label will also be email placeholder will be something like John do at JSM mastery. proo we can pass a different icon such as email.svg and icon alt will be email and check this out I go back and without even reloading the page a new new input is here with a custom icon placeholder email type and everything looks great now let's see how we can extend this to add a phone number field we'll duplicate this custom form field one more time but we'll change the field type to phone input to it we can pass a name of phone and the label equal to phone number it won't have the icon source and alt and the placeholder will be something like 555 1 2 3 4 5 6 7 if we save it you won't be able to see anything yet because our custom form field doesn't yet know how to render a phone input so let's extend it and let's make it happen I will add another case right here where the form field is of a type phone input and then we can return a new form control inside of which we'll have a phone input but of course this phone input is not something we'll create on our own typically there's a saying that says Don't reinvent the wheel and we follow it so there's an amazing mpm package that has over half a million weekly downloads that does what we need it to do it's an international phone number input for react so let's just install it by running the command mpm install react D phone- number- input-- save and let's see how we can use it we simply need to import the Styles and the phone input component and then we use it like a regular input let's give it a shot I will import these right at the top and I will try to call it it should work something like this phone input and and it'll have a default country equal to us if we save it just like this will it work let's see phone input I'm going to go back and yep the phone input is here and you can actually choose from different countries in the world and it should prefill the country code this is looking great already let's give it a placeholder equal to placeholder we can also give it the international FL flag with country calling code value will be equal to field. value and just for typescript we have to say as e164 number so this is a special type or undefined in case it doesn't exist we also have to give it an on change equal to field. onchange and we can give it a class name equal Al to input Das phone believe it or not that's it for a phone input check this out it looks amazing and if I reload the page you can see that it adds the country code and if you change to a different country it automatically prefills it but not only that I can type my own country code and as soon as it recognizes it it will also fill in the flag so we can do one or we can do 91 it all works great or again you can just choose it from the list right here and then continue typing the full number this is amazing and with that we have our base form to add a patient we'll get back to this custom form field later on as we add more types of form Fields but for now let's go back to this patient form and let's figure out a way on how we can submit it instead of having the IR regular submit button will create a new custom component let's call it submit button. TSX and run rafc immediately after we can just call it right here self closing submit button coming from do/ submit button and it we can pass the is loading property just so we know when to stop a button from submitting if it's already loading and we can dive into it and start implementing it through the props we can accept is loading class name if we're passing some different class names and children if you want to expand its looks and we can Define that as button props we can Define the types right here by declaring an interface of button props it'll have the is loading property of Boolean class name which will be optional of a type string and children of a type react number node and the only thing we have to do here is render an actual button so let's render a button coming from slui button let's give it a type equal to submit it will be disabled if it's currently loading so if is loading disabled and we can give it a class name which will look like this if we're passing some custom class names then render that else render a Shad - primary dbn and give it a w Off full next if is loading in that case we want to show a div which will show the loading State else we can simply return the children meaning the button itself this div that will render the loading can have the class name equal to flex items Das Center and the gap of four and within it we'll render a next GS image that will have the source equal to SL assets SL ions SL loader. SVG with an Al tag of loader a width of about 24 a height of about 242 and a class name equal to animate Das Spin and below it we can simply say loading dot dot dot now let's see why this button is complaining it says button is not defined so we have to import it from UI button I think we are good now so if we go to the patient form let's see if we're properly calling it oh it's expecting children so it's not self-closing rather we need to pass the text inside of it so we can say get started also don't forget that this is loading is not defined so right at the top of our form we can define a new use state Cod is loading set is loading and at the start it'll be set to false don't forget to import use state from react if we do this and go back you can now see this beautiful get started button and with that the UI for our o form is done there is one thing that we have to fix though and that is validation right now if you click get started it won't really try to validate things and even if it did it would only try to validate the username which we don't technically have as our field so we have to make it have different values here in the default such as name at the start empty string email at the start empty string and phone at the start equal to an empty string as well but you can see that it's complaining saying that these don't adhere to our form schema and typically it's a good idea to extract this form schema into a new file to keep it all tidy so let's copy this take it away from here and go to our lib within which we can create a new file called validation. TS and before we dive into the validation unfortunately the YouTube limit will cut me off right now we are about to hit 12-hour limit on YouTube so I'll put the link in the description down to the complete video so you can just continue watching to where you're at right now I'll see you there