Transcript for:
Building a Banking Application with Next.js

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 hi there and welcome to a first ofit kind course where you'll build and deploy 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 with an ultra secure SSR authentication a homepage showcasing your balance connected credit cards transaction list and spending categories a page where you can see a list of all connected Banks and the transaction history with filtering and a payment transfer page where you can make transfers to real bank accounts and even other accounts on your platform all of this while learning nextjs with server side rendering group routes nested layouts server actions and more advanced and reusable form management using typescript react hook form in Zod played for payments and it'll work no matter where you are in the world the latest open-source app features that have been released right this moment charts shaten and Tailwind CSS for a modern completely mobile responsive UI and Sentry monitoring software that analyzes performance and makes our bank more secure with improved teaching methods through a completely open source codebase you can refer to if you get stuck a free Custom Design to know exactly what you're build building and even logical diagrams so you can visualize the application's high level architecture and here's a demo to show you precisely what you'll build 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 hand we in on this page you'll find all the details of your connected bank 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 but before we dive into transfers let's connect with another bank account just click here and follow the same onboarding process let's try a different account input some test credentials and boom a new bank is now listed on the home and my Banks Pages this change will also be reflected on the transactions history page where you can view a list of all transactions for both accounts plus you can also filter and view transactions for each Bank separately now let's transfer some funds once again there are many required Fe 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 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 we'll 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 will of course course use react which is the best component library for the web of course we won't use react alone we'll use next gs 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 of react components and when it comes to the banking functionality we'll be using played one of the world's leading banking apis today allowing us to turn this app into a real banking application and not just a budget tracker which you can see on many other YouTube videos will 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 we'll use aite it will allow to build your entire back end within minutes and scale it 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'll learn how to work with it too to style our application will of course be using Tailwind CSS which is a utility first CSS framework allowing us to have completely custom custom Styles and have them quickly without having separate 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 within your application specifically we'll Implement session replay allowing you to get to the root cause of an issue by watching replays of real user sessions within sentury 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 tea and let's get started to initialize our app we can actually use chatsi 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 one 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 ow us some additional type safety and make our application that much 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 NEX GS 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 2 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 understand understanding of how nextjs works then 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 shaten 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 we'll do soon enough and we also need to set up the tailin config which I'll show you how we can do very soon other than that the way that chat SC 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 nuui 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 it 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 we 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 Horizon so you'll be able to send money between real bank accounts right within your 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 flowchart 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 the link in the description and get it for free now hidden 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 this 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 tealwing 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 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 show you back in the figma file I think this is that success Coler you can click on a specific component and then on the right side you can see the corresponding Styles specifically if you go on 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 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 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. CSS 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 IBM _ 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 const IBM Plex serif is equal to we call this IBM Plex serve Constructor and we pass an object with options with subset of an array of Lain we also want to do a weight of an array of 400 and 700 as strings and we want to pass a variable for that font which is going to be-- font D IBM dx- 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 be something like Horizon is a modern banking platform for everyone and we can also give it icons with one icon of SL ions SL logo.svg this is now coming from our assets next we have this root layout which was created for us by nextjs and we 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 intervariable 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 L layout and the off Pages such as login and signup will 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 parentheses 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 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 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 that's doeses 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 o 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 which we'll have a page. DSX and there we can run rafc 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 wi 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 slash 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 off well when you create route groups they're not added to the 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 when 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 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 stuck up to this point you'll be able to check the codebase 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 git add dot to add all of the current files to it and then say something like git 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 an 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 DM 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 here at the top and then you have the complete file and folder 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 where 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- 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 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. TSX 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 are implemented maybe we can just say guest 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 Adrien 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 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 title 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 number and I will make that something like 1,250 let's also add some sense like do35 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 D2 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 colum 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 3 4 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 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 Flex 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 cents but we're going to take it a step further we'll use a special counta 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 countup 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 let's do just that if I go right here and render the count of 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 not 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 use 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 count up 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 hand 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 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 indented 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 2.75 and let's add not four decimals currencies 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- full 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 yes 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 is because it is a client side component so we have to give it 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 charges for that countup Library even for react Char js2 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 Char JS 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 91 F and you might be 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 chart.js 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 ptag 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 op 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 side bar 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 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 side bar first I think that's going to make our app look completely different so going back to our homepage page 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 will 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 when 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 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 we'll 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/ iicons SL logo.svg and as it's an xgs image it also has to have a width property of 34 and a height property of 34 as well and now we can see the logo up here on top we can also give it an Al tag of horizon logo and we can give it a class name equal to size-4 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. Lael 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 different 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 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 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 b G 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 back end 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 used 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 das3 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 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 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- full 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 have to import that image from next image give it a source equal to SL iicons SL logo.svg a width of 30 a height of 30 and an Al tag of 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 Navar so let's create a new component for mobile navbar or mobile na. TSX run rafc in that Navar 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 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 base it right within 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-o for full width and Max Das w- 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 we render an image right within it which we have to import from next image and we can give it a source equal to for slash ions slash 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 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 this snv bar so starting from within the nav all the way before the nav ends so 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 clan 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 D 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 DI so right below this link let's create a div with a class name equal to mobile naav Das 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 Dash 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 indent it 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 over it 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 uncore close and it will also have a w fo 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 will'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 card 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 Min DW of 300 then it gives it a Min width otherwise it's going to be hidden and then when it starts showing it's actually on minwidth 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 eight right within it we can have a self-closing div with a class name equal to profile Das 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 that 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 that 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 Das 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- full and justify Das 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 HF equal to forward slash with a class name equal to flex and 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 slash ions SL plus. SVG with a width of about 20 a height of about 20 and an ALT off 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 -14 f- 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 B 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 Flex D1 flex-all 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 eight Z of zero and W of 90% and it will say bank card too 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 two 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 rafc and we can import it right here bank card coming from that slbank card and we're going to have a second one too 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. firstname 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 false 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 set 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 H ra 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 giving it a specific height of 190 full width and a Max width we're rounding up the corners a bit giving it wide 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 chat gbt 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 semibold and text- white and it can render the accountname right now I don't think we have it so it will just be undefined 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 - IBM dx- serif font dblack 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 below this P tag and below the div we can create the 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 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 D14 font D semi bold tracking of 1.1 pixels this is the space between the characters and text- white and here we can just put three times of four numbers of stars 1 2 3 3 4 1 2 3 4 and 1 2 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 name equal to bank- cardor Icon where we can render an image we can import the image from next image give it a source equal to SL 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 SL ions slm mastercard. SVG we can give it a width of 45 a height of 32 and we can say out 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 we'll 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 4 1 2 3 4 and we don't yet have the account 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 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 route 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 Dash history and we can create a new page. TSX 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 have a page. TSX where we can run ource and rename it to transfer now if we go back to our 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 tool 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 the 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 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 o form. TSX run our fce and then we can use that odd form right within here coming from o 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 odd 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 for 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 odd form component great with that in mind we can dive into the OD form and start implementing it our OD 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 Navar 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 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 are 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 will save our user data so user set user at the start equal to to null and let's properly spell it here and let's import used 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 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 there we go that's good below it we can render a P tag with a class name equal to text D16 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 Das Co gap of four and later on here we're GNA 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 shaten 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 ARA attributes es and labels have support for client and server side validation and of course they should be well styled and consistent with the rest of the application so by using shat cens 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 radic 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 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 it 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 nextjs 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 odd form component will be client 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 validation 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 Ed 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 valid ation 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 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 not 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 type 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 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 chaten component so if you haven't already you need to do MPX shat cn- 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 on submit 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 l 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 Dash class and a pretty cool thing about this input is you can provide any kind of tailin 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 type username as that is the only property we have in our form 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 do 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 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 to 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 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 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 2 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 invent 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 ah 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 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 do 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 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 oth form schema I will import Z right here from Zod it will have an email as well as a password of a z. string and we can do a Min of eight characters now going back to our o form instead of saying form schema three times we can just say o 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 it 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 misspell 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 o 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 shaten 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 the 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 at JS mastery. proo and then for the password you can see string must contain at least eight characters 1 2 3 1 2 3 1 two 3 that's not my real password and there we go we can actually submit the form and once we submit it what happens well we're going to call our onsubmit function which will consol log the values since forms our client side we won't see the cons 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 signin 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 dbn 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 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 two 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 MB SB and then we can say loading dot dot dot if we're not loading we want to ask ourself 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 two in inside of which we can check the type and if the type is 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 can have an hre which is also Dynamic depending on the type so if the type is sign in then we can make it go to forward 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 daslink 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-all 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 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 time remember both the sign-in page and 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 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 birth 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 11 one01 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 EX 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 YouTube 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 this 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 the 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 OD 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 comma now we can look into them and maybe fix them a 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 that Max we can do two and I think we can also do that 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 Min three and then SSN like 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 signin 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. 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 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 odd 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 so 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 Zod 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 O form schema and then we pass a specific specific type and then we can pass sign up in this 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 ajs mastery. proo 231 23123 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 and zad validation so now you know how to make the 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 consol log the error but in the try is where the magic happens here we want to sign up with app right 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- 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 aide and plate 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 consel log not that long ago it contains the email password first name last name address one state postal code date of birth and SSN I 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 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 signin 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 con 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 we are successfully fetching all the data from our front end or from our form you can say both for the signin and the signup 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 can 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 server actions is to define a use 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 Ed server right here or you can just create a separate actions. TS file and and add the US 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 action and we're going to create a new file called user. actions. DS 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 const sign n 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. add error instead of a console log here where 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 to 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 tab script 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 par Rams and before we can proceed any further with this we'll first have to set up our open-source backend tool of choice ight as we use aight here to create a user account so let's do that next ight 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 two 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 uncore aprite undor project and just to make sure that we name our environment Keys the same way we can also create create a new file called env. 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 read me of this project so copy it and paste it here in the EnV example as well as within the EnV and and then you can just copy the one that you had for the ight 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 JS smore 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 app functionalities o and databases let's start with o as we have already implemented frontend Pages for it regarding oth 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 od2 providers anything you might need but once we have our user we have to connect it 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 will be given a bank ID so let's past it under aight database ID and then we have to create our first collection with the 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 app right environment Keys now within the users collection 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 2,000 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 of a type string and the key will be dalla customer URL okay so what is this DW a let's explain that a bit Dua is an 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 duala customer uh URL will'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 require it to true and we need the SSN social security number let's do about 50 characters and the required great and these fields form a user and now that we have the user we are ready to set up our 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 deep into explaining how the serice 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 next GS specifically we'll follow app right's new nextjs 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 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 the 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 as DEC 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 with in 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 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 aight 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 know 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 operate client and setting its endpoint in project so that that operate client knows exactly which aight project it should modify in this case it is our JSM Adrian banking project because that's the ID that we passed 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 validate it and ensure this is the correct aight session so instead of saying my custom session we can say aight 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 aite 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 a node admin which allows our API to do whatever we want with it now we can focus on the four step 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 of 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/ aite we can import the ID coming from node aite 2 by the way I just double click the word and then press control space and that helps me with the autter 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 prams and we have to pass it in 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 account is equal to await account that 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 and now we have to ask ourselves how can we get access to those well thankfully the email is within the user data do 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 D structuring the email the password the first name 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 aight 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 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 that stringify on the user object well we do that because in nextjs 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 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 we go 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 sign up now great so with that in mind the user actions for signup 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 like 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 as a state as well make sure we have two characters postal code has to have round five date of birth can really be anything here we don't have any protection for that and for SSN we can do 1 2 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 OD 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 con user is equal to a weight 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 Andy try to call it here of course by importing the lib and making the function async 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 sent 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 con user is equal to a wait 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 cons loging it 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 cight project database B ID and so on but when we were following aright documentation they might have named those things differently so if we go to aight let's see next public aight endpoint and next public aight project aright endpoint aright project those two seem good what about next ight key that's what I called aight secret so instead let's follow their docs and let's rename our EnV to next app right key and we can also do it in the EnV example next aight key instead of the aight 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 at gmail.com and my password and sign up looks good we are 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 signup 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 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 dot 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 our 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 say const 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 sidebar and instead of user. first name zero say just user.name and here instead of rendering those two we can just render user do name and we'll have to dive into the right side of our 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 logout 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 catch we can simply return null and in the try we can get the account from the session by saying const and then D structure the account is equal to await create session client and then we can call the cookies. delete and we can delete the aight 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 side Side Bar 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 created 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 let's quickly navigate to Mobile nav and at the bottom we can call this same footer component coming from do 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 user's 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 do 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 Das bold and text - g-700 and 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 by 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 uncore 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 -14 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 relogged 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 f- normal and text- gray- 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 it a font D semi bold 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 uncore image and we can render an image which we have to import from next image give it a source of icons SL logout . 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 wait 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's 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 a 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 the 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 rout 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 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 Dash 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 OD 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 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 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-o justify between and font Das enter 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 iicons sl- 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 1 two 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 IM immediately get redirected to the home because then we wouldn't be able to see anything 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 off session that is great soon enough you'll connect your app with play 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 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'll 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 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 slon boarding to your URL and it should renate you here now let's click Start under install s entry let's choose nextjs and configure as decay it'll give us a special command which we can use to spin up Sentry 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 do 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 Sentry 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 next GS 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 versell 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 serverconfig this initializes is 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 senty 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 sentury 100% this means that all transactions created in the app will be sent to sentury 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 sentury example page press enter and here is that sneaky button throw an error there we go the error has been thrown Sentry example frontend 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 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 and more stuff but what I want to know is exactly which user broke that and we can see the users 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 do as an example I'm going to do a very cool address in a city let's do Los Angeles and let's do la with a postcode of 1 2 3 45 date of bird can be some random numbers Social Security numbers can also be random email is going to be very secure email at 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 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 Century and see if we already have a replay it doesn't show up directly on the replays 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 centry 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 VI 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 Sentry of course there's so much 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 you can even track Errors By country Errors By browser 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 deployer 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 play 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 aite 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 plate 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 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 laws 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 onboarding 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 play 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 plate to our servers site application and then through play 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 it 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 the 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 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. TS within here we'll need to set up a new play configuration and alongside installing react play link we also need need to install the general play package by running mpm install played now we can import some things from pled 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. 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. plore centore ID as well as a play- 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 app right you do the same thing you create a client and expose it to your app and then you can use that app client to do all sorts of things in a similar fashion you create a PL configuration and a PL 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 imported right here within the odd form play 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 destructuring 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 OD 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 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 Turner 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 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 plate 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 Ed 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 recold 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 US 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 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 await 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 prams 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 forward slash great so now we have laid out the foundation for on success and the token with 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 PL 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 destructure 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 blade link from react blade 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 in its current state it is indeed disabled 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 play 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 provided a client uncore 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 plate this is just for typescript we can also choose a language in this case I will make it en n for English and also country uncore 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 per Rams but the question is where is this played link coming from well we have created it before it is coming from the play file export con play client so let's import it at the top by saying import played client coming from add SL Li slpl 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. linkor token and there we go that's how you create create a link token using plate so going back to our odd form or rather to our plate link component we can uncommon this part where we get and set a new token make sure to import create link token from lip 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 create it 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 third party 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 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 played 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 consal 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. 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 response 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 plate 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 at 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 dalla customer ID the processor token in 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 on 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 a 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 ser 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 called dalla and allow theirselves 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 d. actions. TS 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 quick Qui 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 whereare 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 initi iate a transfer which I found under dalla docs you basically have to form a request body and then do a post request on Dua 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 you now have access to these Dua actions and we just have to make sure to install D- V2 in our terminal by running mpm install D- V2 after you do that it should go from red to green and we can import add funding source from Dua and I want to take a second here to explain what Dua is on our logical map well first of all we have the main bank application and of course pled 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 UR L 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 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 within aite 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 D structure specific values such as aight _ database 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 aight we can even rename it to just database ID so to shorten it a bit and we can repeat this process for aight 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 string ify 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 app right 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 aright 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 this is a reference to our user account so instead 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 n and click create there we go now we know 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 play 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 Infuse it with played 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 this 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 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 that means that we have reached line 48 in my case we want to create a dalla customer URL that is our payment processor if you remember so we can say const dalla 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 the type of personal now we want to check if we have received the Dua 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 Thea 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 tri 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 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 dalla customer ID as well as a Ola 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 typescript 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 a 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 off form and the only reason why typescript right 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 tapescript know that we know that we'll have that first name there if we are on the sign up 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 of 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 uper 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 aight 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 some how some of you already found the link to the application which I'm currently 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 dla let me take some time to explain it once again play and VOA 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 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 Real Time payments so while played acts as a bridge between apps and banks for accessing financial data dalla is more about facilitating actual money transactions you would choose to use dwala when you need to 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 HT TPS Colin ai- sandbox. w.com make sure to spell it properly and then VOA 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 or just test so back in our OD form here we can bring back this if user then show the play 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 debug on the go I'm GNA 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 would recommend that you copy the same thing that I have n y 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 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 aight 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 dalla as it looks like it succeeded in creating one so let's deactivate the customer 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 go to our user. actions. TS and go to the signup form we're accepting all of the data Here sign up Rams 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 for wraps 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 Ed 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 dalla 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 aite 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 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 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 slow and our connect button has a nice shade of 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 aight field or if maybe you misspelled the way that you call a field within aight 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 played 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 institutions 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 ples 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 vaa 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 undor 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 Adrian JS Mastery let's continue and 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's 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 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 ID 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. TS 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. DS 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 ALS Al 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 readme 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 promise. 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 doac 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 the 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 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 of a type get Banks props and of course it's an arrow 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 we 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 quering 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 homepage 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 do 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 to homepage as that shouldn't happen and after we have multiple accounts we can get further dat for a singular account by first fetching the ID of that account in the database by saying const aight item id here we can make that equal to in parentheses ID as string or accounts data zero question mark. aight Item ID and instead of accounts data it's actually accounts question mark. 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 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 per apps in next GS you get access to the search prams right here and then from search prams 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 da 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 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 sign up we also store this session and it's important to store the 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 string IFI 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 try and 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 and ID rather we're querying it by the user ID which we compare with the user ID which we're passing through perams 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 questionmark doir name it's also possible that sometimes we called it 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 get 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 label as well as the data points we 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 params even though it sounds like it could be a number is actually a string so we need to create a new const 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 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 transactions Das 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 hre equal to a dynamic template string of SL transaction Das history slash question mark ID so we're passing an ID parameter equal to aight Item ID and this is basically the ID of our specific bank account so if we're 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 CN UI latest add 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 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 parentheses here for each one of these accounts as I said we return a tabs trigger with a key equal to account. ID 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 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 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 aide item id which is equal to aide Item ID and now you can see this gray tab that currently only says played checking as that's the 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 app 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. aite 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 component 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 aight 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 our afce and we can import that component right below the bank info but 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 shaten responsive table component which is simple Sleek yet it gets the job done so let's copy the installation command and 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 stable 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 thisable header we'll give a special class name of BG Dash hash F9 F FB I found this color 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 B 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 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 will display this actual data and this table will be highly customizable we'll be working with with different colors depending on whether it's an income or a deduction we'll be checking for the status removing special characters from the name formatting dat 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 action table props and we can map over the transactions by saying transactions map where 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 it status whether it is processed or pending and we can do that by saying const status is equal to get transaction status coming from lib utils where we pass a new date of T.D 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 2 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 from utils to which we pass the t. 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 action 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 do 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 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 can render the status so that's t. 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. dat 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 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 our 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 hash 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 add the color let's also style the table cell by giving it a class name equal to maxw das 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 -14 truncate font D semibold and text- 344 054 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 off two padding right of 10 font Das semi bold that's look 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 De bit 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 # F 04438 which is a red color and else the text will be off 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 table 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 transaction stable 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 Dash full and below that div we will have a P tag that will have have a class name of CN as well you'll soon see why 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 C category is equal 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 back 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 C 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 expanded 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 the transaction category Styles let me show you how you 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 /pl link make sure that you use the one that we have created so this is the one coming from played 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 not not the primary one but rather we have these different like 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 Das 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 where 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 / iicons SLC connect db. 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 D semibold and text - black-2 and while we're here we can basically duplicate this image and the P tag and added 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 we 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 already 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 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 account's 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 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 switch 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 what 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 destructuring 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 weit 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. 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 text -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 the speed tag and instead 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- 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 course let's properly close it right here and you should be able to see the total amount 110 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 with this 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 will 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 we'll 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 pled 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 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 that mask because we're already destructuring the data so now this one is 0 0 0 this one is 11 one one we can also give this card A Min width so something like m-w Das 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 use used right here in the page Flex wrap they're all 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. aprite 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 Banks 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 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 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 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 passed 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 defined 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 Shay 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 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 opened files and navigate over to the transfer page right within the transfer page we can turn this into a section and 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-4 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 requires us 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 OD 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 a lot 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 comp components create a new component called Bank dropd 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 have haven't used it before so you can install those two packages once you do that you can fix the import for the bank dropdown 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 bu 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 this get Bank 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 into 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 a sync 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 back 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 doaction dots 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 consel log 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 undor ID then we have to pass a transaction underscore collection uncore 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 aore 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 aright 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 office 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 required then we need the sender ID D 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 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 R let's just make sure that we're importing it from a proper file for 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 homepage is looking great let's move on over to transfer funds and 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 play checking to play savings by copying this sharable ID going to transfer funds I'm going to add a node 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 a trans section but just above we're creating creating a real transfer using Dua so how can we verify that a payment has indeed happened well let's go back to D's 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 two 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 that 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 do equal where we're comparing the sender bank ID if it's equal to the bank ID want a query 4 and of course we have to import query from node aite and this bank ID has to be D structured right here at the top so it has to be within an object sign great now after we get Sender transactions we also want to get 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 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 data. receiver transactions. documents and finally we can return par stringify transactions amazing now back in Bank 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 all 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 once 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 two days for the transfer to take effect exactly as how real Bank transfers work and if we switch over to play saving you can notice that here we also have the new transactions but this time they're green as we're adding money to the sings 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 transaction stable we want to create a new component so let's go to the components and create a new pation TSX and we've implemented pagination on many videos in this channel but we have explored absolutely all advantages of doing server 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 pation 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 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 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 on 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 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 pagination we can uncomment it and we can pass it all of these grade 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 re 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 10 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 in 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 for Rams 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 p ation 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 more sense than the card that says Adrien and now we can see play 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 das1 Flex Das Co 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 das2 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 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 cons 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 rafc 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 console log it to see what we're getting or even tabp and 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 a 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 code it yourself first and since I've imported it I'll also have to add a shatan progress so let me do that by running shaten UI 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 and not export 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 cn'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 shaten 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 the this progress primitive indicator by wrapping 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 free preview 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 serers 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 4mon boot camp where we prepare develop ERS 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 MJS 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 fig 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 deploy our 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 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 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. cell. apppp 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 Sentry variable so go back to your code and go to the 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 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 our 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're 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 a at 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 doco 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 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 in bottom right are looking great the mybs looks good too we can see only a few transactions for this account which is good we can navigate over to the trans trans action history of this account and see all the sandbox transactions 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 app Pride for our database Sentry for tracking and session replay and don't forget we have also done a lot of work with shaten 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 recommended 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 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