Flutter Mobile App + Node.js Back End Tutorial β Code an Amazon Clone [Full Course]
"WEBVTTKind: captionsLanguage: enIn this course Revon will teach you how to build a full stack. Amazon clone, featuring an admin panel using fluter and no JS let's get startedIn this e-commerce app, we will learn about email, password, authentication, state persistence, searching products, filtering them based on the category, rating them based on which we will be able to see deal of the day, adding them to cut, checking out with Google or apple pay and viewing the details of past orders and the status. On the admin side, we will be able to add products, delete them, see total earnings and view the graph of sales. Based on the category. We will also be able to view the orders and mark them as pending completed, or received to follow along with this video, all you need to know is the basics of flatter and dot. There's absolutely no need of knowing anything about no JS express or even Java script. If you're familiar with Java script, it's great. But even if you're not, don't worry, it's pretty similar to dot.I'll explain the differences as we move ahead in the tutorial, repeatedly follow similar processes of crude. Those are also give some exercise as we create certain APIs, which you can check with the solution. I type after following this tutorial, you'll have the capability as well as confidence to build your own complex app with this technology. All right. So the very first thing we need to do is open up a terminal and in your run, the flatter create command. But before that, I'm going show you the flatter version we'd be using throughout this tutorial. So we are using flatter two point 10.5 and that version two point 16.2. After that, we can turn the flatter create command. I'm gonna call my project name, Amazon clone tutorial, because I already have a project named flatter Amazon clone not to get confused with it. After that is done, we can migrate to this folder and open it in vs code. I will open it in vs code using code for stop. And then it opens up in vs code. That's great. After that, we can go in the live folder in the main door dot file. And before removing any boiler plate code, what I'm going to do is select IO simulator. If you're not on Macs, then IO simulator will not appear because it's only for Mac. So if you're on windows or Linux, you can always use the Android simulator, make sure that you have Android studio install. After that, we are going to go over here in the run and run without debugging. You can keep this, uh, shortcut in mind, which is present here, which will help you debug your apps faster while this is being loaded. What we can do is remove this my homepage class that we have. We don't need that and make sure to not save it otherwise, you know, it'll give some errors while debugging away. So you'll think that the problem is coming from the default app project, but it's because you've saved. So make sure it's unsaved away after that. We can make sure and check, uh, change the title, which will be Amazon clone and remove the theme data. We are going to modify it in just a bit, but you can see our app has launched so we can see how it's looking. It's functional. That means our default project is great. So we don't need to worry about that. We can remove all the comments and you replace the text with this text, which will just give us a very bad output, which looks something like this. Great. That's what we expected. Now let's change the theme data, where to change the theme data. We need some colors. So for colors, what we're going to do is in the lip folder, create a folder called constant.In this folder, we will have all the constant files that we have, for example, global variables or any utility files like functions that are being repeated again and again. So yeah, we are going to create global variables.dot file. After that is created, we can call this global variables as a class. We're not going to create any stateless or stateful budget. This class is going to contain all the static variables that we have because their value isn't going to change ever to get the colors. What you're going to do is go to this website. I'll mention the link in the description below. This is my repository on, get up. Then you can copy all the colors that you can see if you want. You can also copy the static images and the category images that we are going to copy on later on. But for now, let's just copy all these colors that we can see and paste it away. After that, what we need to do is go to the top and import material dot and alls go away. Then we can go in the main dot file and you change the theme data. But before changing the theme data, what I'm going to do is wrap my text widget with a scaffold widget, just to demonstrate what we are going to change. And we can see that in action real time. So here, I'm going to mention the body as this text, and then obviously wrap it with the center widget so that everything comes in center here. I'm going to press command full stop and add a cons modifier, wherever it asks me to. And over here as well, I'll add a cons modifier, Ania cone, modifier, and all our errors go away and just add trailing comma so that it forms your document. After that we can come here and you can see, we are seeing a blank scaffold with just flatter demo home page showing away, which is this text. Also, let's just add an app bar, which will be nothing but a simple app bar with the title that says Text, hello, and then remove the constant from your, and put it for the center text. Great, and put a constant over your as well, and then just save it. So here we have the, uh, blue app bar. So the very first thing we need to do is cha change this background color. I don't think we need to change it, but just, let's just specify in case you want to switch teams for your app, or you wanna make it look a bit different. You can do that using the scaffold background color and use global variables dot back variables, not background color. So you can see if we go to the global variables class, we have background color there, which is white, but in case you want to change it to black, then you can change it over your and save it. You can see it change to black, but in this case, we just want it to be white.So yeah, we have it white. After that, we need to add an app bar theme. So the app bar theme is going look, something like elevation set to zero because all our AB bars are not going to show any elevation. You can see there's some elevation here. We don't want any of that. And we want ICAN theme to be ICAN theme data whose color will be black. So all our I icons that show up will be turned to black color. And we want that because in case we change the app by color, which we are going to change to something gradient. Then we want the, I can theme data to remain a constant there, which will be a black color, no matter what. And let's just put a cons conveyor so that all our warnings fade it in case you're wondering what, why am I getting these errors side by side, like this, I'm using a visual studio code extension for this named lens. So if you go over your, in the extension tab and search lens, you can see error lens showing up. And this is the word, the thing that I'm using, it's really great. I would highly recommend using this. Great. So our icons are now black. Next thing we want to do is make sure that if we add any button, it shows up as a golden color or something like that. So what we can do is just to demonstrate what I'm going to do is wrap this centered widget with a column widget and then add a button away. So I'm gonna call it elevated button on press will be nothing. And the child will be a simple text saying, click and we'll ignore the arrow warning for our warning. And now we save it. You can see this is the blue color showing up. We don't want that. So what we are going to do instead is In the theme data, add a color scheme with this. We are going to specify that the color scheme is the light color. So we have color scheme dot light. And then we want to pass in the primary color, which will be global variables dot second secondary color, which is almost like a golden color. And with this, our AB bar and our button both have changed to golden color. So that's great. But we are obviously going to change the AB bar color continuously, and we are not changing the AB bar color. You are in the color, something like this over here, because if we specify something like that, it takes in a color argument and we don't want to pass in a color argument. We want to pass in a linear gradient. If you go to the global variables, you can see this is a AB bar gradient, and it doesn't accept any gradient.There is no way for us to pass in an ABAR theme, which is of the gradient color. So we'll have to do it manually every time we use an a bar. So that's why I've not mentioned anything here, but this color will make sure that literally everything that shows up except the text and all of that stuff shows up as a golden color. And that's exactly what we want having the color set in place and the team looking great. What we need to do now is in the left folder, I'll show you the folder structure that we are going to use. So we are going to have a features folder where we are going to have all the features that we have. For example, we have account, we have card,We have homepage, we have order detailed screen. We have product detailed screen. We have search, we have address everything that is there is going go in. This features folder. So for now we are going to have a screen because that's the first thing we are going to work on. And in this a feature, we are going to have three folders again, which is screen, which is all the screens that the O is going to have, which is just the odd screen. But in case we have many screens. For example, you want to divide the O screen into login and sign up screen differently. You can add both of them in this screen's folder. Then the next thing we want is widgets. So the reusable components in our odd screen, and just to divide the screen into simpler parts, we're going to have widgets. And then finally, we are going to have services. This is going to contain all the business logic that we have, like going to the server, connecting with our server, fetching some data, sending some API calls, all of that is going to be done in services. And now in the O screen, we are going to go there and create O screen, do dot file. You, we are going to import material dot, then create a stateful widget. And then we are going to have odd screen, pretty simple. So we have the stateful widget ready? Yeah. We are going to return a scaffold. And now there's the main thing of our app, which is routes. So how are we going to navigate between pages and our application? We can use that using, you know, something like you can use something like navigator, right? So V navigator dot Push, and then we need to pass in material page, route. That's a lot of boiler plate code to write. And considering we have so many screens, it's a lot of code to write again and again. So instead what we are going to use is named routes. So named routes are something like navigator push named, and then we pass in the context and the route name that we specify now, what is the problem with named routes? Yeah, we have to go in the main.dot file, set up the routes and that, that all isn't the problem. The problem is what if you want to pass in some arguments, right? So your, if you pass in some arguments and then just to accept that argument, we have to write so much of boiler plate code again, and that will be a lot of work to do. Instead, what we are going to do is go in the main door dot file and use something known as on gen route. So yeah, I'm going to pass in the property on gen route. This on gen route will run every time we use push name route or any other named routes that we have, and it'll run the call back and it'll run, whatever is specified to it. So that we'll have to go to the left folder and your create a route, not create a folder. Actually let's create a file called router.dot, where we are going to have a function, which will return a route, which will be dynamic. And let's just import route here. So let's import material package and then create a function called generate route. We are just creating this file so that it just is a needer way to look at it. I mean, there's no need of doing it, but it just looks neater. And here we are going to receive route settings and route settings will give us any data that is useful in, uh, constructing a route. You'll see that when we use that, and then over here, we are going to have a switch and a case statements because we are going to have so many routes in our application. We need to match each and every route with the route that we pass in. If you don't understand, don't worry. So you're in the switch. We want to pass in settings.name. So if anything, and settings is not showing up away, so let's just take route settings. So we are going to match route settings name, which will be the name of the route that we specify. We need to match it with any of the cases that we are. So first case we are going to have is the odd screen. So we have odd screen, but we need to pass in the name, right? Because this is the type string. This is not a string. This is a widget. So what we can do is pass in slash offscreen away. Now that's a good way to do it, but even better way to do it is just go to just copy this line, go to the offscreen and create a static variable away at the top called static, constant string, route name equal to, and then passing the odd screen route. And now we can use odd screen, route name everywhere so we can have odd screen, route name. That's a cleaner way to do it. Now we don't have to write, uh, slash offscreen everywhere in our application instead just use offscreen or routing name, thus reducing our errors overall, after that, what are we going to do? Well, we wanna return a material page, route. That's simple, right? We already know about material page, route, and then in the material page route, we want to pass in a builder, which will not do anything for us, whatever context that it gives us. It's no use for us. And then we are going to return the odd screen and yeah, we have it. That's all that we need to do. And in case you want to pass in the settings as well, you can just pass in route settings. And in case you want to remove this error, what you can do is pass in default aware. So this will run whenever any of the routes that we have aware that the name that we have do do doesn't match any of the cases that we have. So I'll just copy this. And instead of actually, let's remove this. And instead of showing the odd screen, what I'm going to do is create my own custom error. So here, what I'm going to have is a scaffold, which will have a body centered saying that the screen does not exist or wrong page error, 4, 0, 4.You can style it according to your visa and needs, but I'm just going to go with this. I'm not going to spend much time on that. After that we have the on generat route property done. So here, I'm going to take settings, which will be received by the on gen route, which will be given actually. And then we are going to use generate route, make sure to import this package, route.dot, and then pass in the settings that we receive. And there we have it. Now, if I take this elevator button and use navigator dot push name, and then pass in the route name, which is earth screen, route name, and now let's just restart the application. And if I click over here and we don't get transitioned to the next page, and that's simply because we have this error saying that the context used to push up or route from the navigator must be that of a widget.That is a descendent of the navigator widget. Basically what we need to do now is just grab the elevated button with the builder and that should do the task for us. So if I restart the application, click on click and you can see we transition to the router, sorry to the off screen.dot file screen file because we haven't specified anything. Great. So that now that it works, let's just remove this home thing because we don't want that. It's just for demo purposes. So I'm gonna remove that. And instead passing offscreen, obviously we are going to have some logic in the home later on when we have the home screen ready as well, just to post the state of our application. But we look into that later one step at a time. Now let's just click close the router dot file and the global variables and go to the off screen.Now let's design this empty screen with the login UI that we want all. So now with me, I have the screenshot of the app that you're going to build. So this is just a home screen layout. Let's break it down and then build the UI for this. So, first of all, the first thing to notice is that they are in a column widget because there's a welcome text. Let me just take this away. We have the welcome text. Then we have a radio button, which is this button. We have the radio button aware, which will, which when click will give us the form that we have with the name, email, and password. If we click on sign in aware, it will give us a form that will tell us that this is a, uh, name, email, and password that's required. So let's build it out. Very first thing to notice should be that we are not putting welcome over here. So we are using a safe area widget. So let's go to the scaffold and in the body person safe area. Now it'll not our welcome texture is not going to appear somewhere away. It's going to appear somewhere away. We have eliminated that UI bug. So to say, after that, we are going to have a column <affirmative>And then we are going to have children in that. And the first child that we have is a text, which will just say welcome. So let's create a welcome text and it's going to be a constant. We already know that because it's just Because it's just a text saying that, yeah, it's welcome. And it's static. Nothing is changing over here. So after creating that, let's see if you're outputting very good. And you can see there's some padding constantly over here in this side. So let's wrap our column with the padding widget. So we have padding and we'll just put eight. That looks good. Great. Now you will also notice that the color over here is somewhat grayish and in the form that it's selected, it's going to show up white. So let's pass in the background color as global variables dot background, color, gray background color, sorry. And yep. This looks great. Knowledge just increases font size of welcome style, not stretch style style, which will be textile of font size 22 and font, weight of font, weight dot w 500. You can test out all the values and then come to the conclusion, whatever you want. But yeah, we have this welcome text showing up. Now let's create this radio button kind of looking thing, which is this widget. And then if it's selected, then we are going to show this. So let's first of all, create these two radio buttons. So to create these two radio buttons, what we're going to have in the text widget is a list style, pretty simple, a list style, which will have a title saying constant text, create account eight accountWith a style of textile font weight. Do we're not going to increase any, uh, font size because it's looking good to me. And we are the create account. Now let's add the radio button. So in the left style widget, we are going to pass in the leading property, which will be radio. And here we are going to have an active color. So let's pass in global variables dot secondary color. Then we have the value and here we are going to create an enum for the value. So let's go right at the top Outside of the stateful widget class that we have. And here we are going to create an enum which will be called O and here we'll pass and sign in and sign up. Basically this enum will keep track of the radio button that we are on and we'll give the value to our radio button. So here we'll have O dot sign up as a value because whenever we click this radio button, we want the value to be signup. And the group value is of the type. So let's go at the top and initialize this enum. So we'll call equal to dot signup with this. We are basically telling that this is the instance of our enum, which will be the group value and the signup Orthodox signup will basically tell that, yeah, this is the default value that we want. So whenever we land on this page, we want the signup screen to show up. If you want, you can pass this as assignment, but it wouldn't make sense for a new user and then pass in group value as an instance, variable of the class or the, or en I'm sorry. Then we wanna pass in an unchanged property, which will give us a value of type oath, and let's just call it value. Great. Now this data type is because we've passed in the group value and the value as Orthodox signup in case we change any of them, this value will also change. And here, what I'm going to do is set state and set a global variable that is a equal to the value that's given and just passing a semicolon. But you can see, uh, let's just keep it in valve because this is the parameter. And you can see a value of type O can't be assigned to variable of type O. So we just need to make sure that it can never be Nu great. So we have this list style ready. Now, if we go by this list, style shows up and it's selected as well, because we have passed in odds, sign up as a value in case you want to change. We can just pass in odds dot, sign in and restart the application, and you can see it's not selected. Now let's change it back now, after having that, let's just copy this list style And paste it again. And this will be the sign in part. So we'll call this sign in. You can see that's the name of, and with a full stop. Yep. And then we need to scroll down and in the radio button, change the value to T sign in and save it. Now we have the sign-in app already as well, and it's showing checked away because we are changed and we are not restarted the application. So let's just restart it. And yep. We have create account showing up. Now we need to show the form that we have now, how do we show the form? Let's work on the form part first, and then we can change the color and stuff. So whenever we click on this create account, we need to make sure this is visible. Otherwise, this is visible. And we are going to make use of this variable that we are. So what are we going to do is in the left style here, we are going to check if OUM variable is equal to O dot signup, then we want to show something. So what is that? Something going to be well is going to be a form which will have a key. So let's pass in a key with this form. We are going to make validations in our application. So if the user clicks on signup, it'll give us proper errors. That, yeah, name is not entered. Email is not entered. Password is not entered and any other validations that you want to perform. So this form is a great widget. So we want to pass in a key and we have to create a global key right at the top to use it. So here we can come and create final sign up form key, and this will be equal to the global key, which will be of the generic type form state. And that's it. And as we are right at the top here, let's create one for signin form key as well, because we're gonna do something similar for sign-in. So let's create that and key. Now we can copy this, go by here, pass in the sign form key. And now we need a child. Now, what is a child going to be? Well, that's pretty simple, right? A column widget, which all with all these text field inputs. So we are going to pass in column and yeah, we are going to have three fields. So instead of just reusing the widget again and again, I mean, writing the code for one text field, then again, writing then copying it and pasting it for another. We are going to create a widget for it, which will be reusable. You can put it in this widgets folder, but I know that in future, we are going to use this text field input everywhere in our application. So what I'm going to do is in the lip folder, create a folder called common, which will describe all the common things that we have. And let me just rename it. So we have common and this common will have widgets. It will contain anything that you want, which is common. Like, you know, some other view or some other widget, anything, then it'll have custom text, field or dot. Yeah. It will import material dot, create a stateless widget, call it custom text field, and your return, a text form field. Why are we using text form fill instead of this text, field widget, because we are going to use validator with this validator. We're going to make validations. And if any of the error that gets thrown, it'll be called by the form. And it'll throw that error on the screen, which is great. After that, we need to pass in a controller. So we have to accept that from the constructor. Then I'll accept it later on. Then we have to pass in some decoration. And how is it going to look like? So we want some borders to show up. So in the decoration, we are gonna have input decoration. Then we have border equal to constant outline input border, because we want the border to show up as the outline. Then we want a border side which will be border side, and let's give a custom color for it. Let's say, say colors.black. And you can pick any shade that you want. I'm just going to go with 38. It, Then I can copy this border Pass in the enabled border. And this is going to be the same thing as this one. And then we need to pass in validate. So we have the validator here. We're going to get a value. And then we are going to return something. We'll put the validations later on. Let's just accept the controller from now, for now. So we have five text editing controller taking the controller, accept it from the construction. Now let's just take this controller, paste it over here, and I'm not going to resolve any of the warnings that I see where, because I know later on, we want this to be constant because this is going to change. And let's just put a custom text feel over here. Let's have it. And we are not able to type because we will have to pass in that in children. So we now have custom text field and pass in the controller. Let's create a controller right at the top. So we have final text editing controller. So what controllers do we need? Well, first of all, we need email controller, which will be equal to text editing controller. And the thing to note here is that this email controller and the password controller are going to be used in both sign up and sign in, because you'll see that later on, I'll show your demo of why we're doing that. Then we have password controller and then we have the name controller, All right. Now having that, let's just create the disposed method right itself so that we don't have any memory leaks and you know, all that sort of things. So we have this and dispose this controller, and I'm going to do that two more times for password and name controller. Great. Now we can go down and pass in the controller. So the very first controller that we want to pass in is the email controller, because we want to pass an email. So we have that and we see that away. Now only thing that is different here is that the name is showing up here. So that is the hint text. So we can go away here, take the hint text from the input decoration. And this he text is going to be from the construc as well. So we have final string, he text. And now in case you don't want to type it again and again, you can click on this, be I and allow, actually be by and then click on generate construc, constructor pass in the he text. Great. Now we'll pass in. He text here and the he text, what is the he text going be? Well, it's just going to be emailed. Great. If I restart this, let's restart the application. You can see email showing up. Now, if I click over here, you can see our validation. Logic is also working. I mean, switching the radio buttons because when I change this form, doesn't show up. Now let's create one more, which is for the name one. So I'll create it at top and we'll have name pass in the controller as the name controller and also a sized box. And the high wheel specify is 10. Again, we'll take this and past it down here for passwords. So we have password and pass in password controller looks great. Now let's add a bit of padding over here because you can see it's way too outside and we want just, and we want it to be a little bit inside. So what I'm going to do is wrap this with a container and why are we doing container and not padding widget? Because we want specify the color as well, because you can see that the color here is just like the background color, but earth it's white color. So what are we going to have? Well, a PAing widget, which will be constant Agent sets all eight. Then we want pass in a color and the color is going to be global variables, background color, because we want it to be white. Right? And yeah, we have it. Now, this looks very bad compared to this. And that's mainly because This color that we have, you can see this is also white, but this is not white. And we'll do that logic later on. But for now let's create the signup button. So for signup button, again, we are going to create a custom button because you're going to use that button again and again, throughout our application and not just in oath section, we're going to import material dot, take a stateless widget, call it custom button. And then we are going to return and elevated button. Now, how is this elevated button going to be like, well, first it will have a child of text saying, yeah, we want to pass in some text, which we accept from the constructor. Then we want an on tap actually on pressed over here. And then we want that from the constructor as well. And then the style, how is this going to look like? Well, it's going to have certain size becauseIf we put it now it'll not have a correct size. It'll just be very small. So what are we going to do? Elevated button.style from pass in the minimum size, which is going to be of the type size pass. First, we need to pass in the width. So the width is going to be double infinity, whatever, and how much ever space we get. And then 50, which is the height. It is going to be a constant because this is a height 50. Now let's accept some things from the constructor. So what are we gonna have? Well, first of all, a final string text, then avoid callback, which will be on tap. And then finally, yep. That's it. And now let's take this bell. I, or alarm bell bike. Sorry, take this on. Press pass in the on tap and yep. <inaudible>, let's take this custom button go to the off screen pass and a size box. Again. It's always PA good to pass in a size box instead of a container, because it can be a constant container. Can never be a constant. And with this constant, it makes sure that the widget doesn't rebuild. So a height doesn't rebuild. It doesn't affect the performance of the app too much, but it's increasing it. Uh, which is good. Then we can take this custom button pass in the text. So we want the text to be sign up and let me put it in the string sign up. And the on tap is going to consist of the validation logic again, meaning calling the form key, using the form key, which is a layer and then performing all the validation, insert in the text field. Great. Now, if you go layer the other sign up button and it looks, and it looks great. Now let's change the color. So let's go at the top. And here in the left side, you're going to pass in the tile color. Now, what do we want? Whenever this button is selected, we want to show as white. Otherwise we want to show it as this gray background color. If you take this example, you can see since this part is selected, everything over here is white, but everything over here is gray. So yeah, we are going to check if O is equal to oth dot signup. So if the variable that we have, which we are changing every time we are, is equal to sign up, then we want to use global variables, do background color. Otherwise we are going to use global variables, gray background color. Now, if you go where UNC it's looking great. Now only thing is let's just shift this welcome text over here. So in the column, you're going to have cross access alignment as cross access, alignment dot start and save it. Now it looks similar to this. Awesome. Now let's just do the same thing for sign in. You can see when we click away, we see nothing. What we need to do is just copy this container that we have created. We can copy that and paste it down in the list below the list. And here let's go over and we'll have oth signin. The container is not going to have any property name, name. So let's remove that. We are going to have email and password and the controllers are going to remain same. We're not gonna change the controllers for email and password because see, in case if user is logging in, but by mistakes, doesn't see this create account and passes in some email, like test other age.com, pass in the password as test 1, 2, 3, then decides, oh yeah, I changed it. I mean, I want to sign in. Then we can click on sign in and directly. This text field will have the values that we passed in earlier in this create account. So that's what we're going to do. So we will have sign in. We're not passing in on tap for any of that. We'll perform that logic later on, but for now we have a basic understanding of what's happening here. Also, let's just go at the top, copy the list, style, color, property, and pass in for the, uh, signin block. And you change it to T signin. Yeah. Now let's restart our application and see how it's looking. We are the create account. If I click over, I have the signin showing up. Suppose I pass in test other gmail.com pass and test 1, 2, 3, and then I decide, oh, sorry. I need to sign in. And we have all the test, all the properties that we passed in over here, the same as your great. Now the next thing is, whenever we click over your, we want to send the data to server. I mean, of course we are going to perform some validations, but before that, we, but after that, we are going to send some data to our server. Now, how are we going to create a server? We're gonna use node GS for this. The most common question for big nurse is what is node GS and why should we use it? Well before node JavaScript could not be used as a general purpose programming language. It was limited to what the browser allowed to do. This means JavaScript only worked on the client side and could not be used to make something like a web server with introduction of no GS. This completely changed using JavaScript. Developers could write code for server, even command line prompts, but you're not going to talk about them in this tutorial. No GS is built on top of the V8 engine. The same JavaScript engine that is used in Chrome. It's mainly red in C plus plus does it's pretty fast and used in production. Let's go to their official website. No js.org link is mentioned in the description below. Check it out. The JavaScript environment provides access to builtin libraries and objects so that it can interact and make our code work. All right, now let's just install no JS in our system. So here we have two options. And if you're on windows, it'll show windows over here. If you're on different version of Mac, it will show you something else, not X 64. So here it shows us two options to install it. Either we can use the LTS version, which stands for long-term support, or we can use the current version. We are going to use the current version, which is 18.1 0.0. If you're seeing this in the future, then there are chances of this getting increase and you, and you're good to follow along with this tutorial. As long as you have 18.1 0.0 or higher on your machine, now let's install this and wait for it to get installed, to assist you. All right? So the installation has gotten over. And if I see over here, it's mentioned in the downloads. I just have to double click on this and yet it will ask me certain stuff. I'll just click on. Continue, continue. Agree to it again, continue then click on install. And here I need to enter my password. After entering the password, it is validating all the packages and it has installed no JS version 18.1 and N PM. We'll talk about N PM later, but here we have it installed. All right. Now, having that in place, make sure to keep this in mind.Uh, you can just save it somewhere because if it's not installed, then you have to manually install this in your path. And then the node JS will be installed. Now let's move this installer to bin and close this and go to a terminal. And yeah, just to verify if it's, if it has been installed, we can type no do no dash version. And here you can see version 18.1 0.0. If it's not showing the current version, that means node have not been installed. You have to do some path configurations, make sure to do that. And then it'll show up this version. All right, after having that in place, we need to go to our project and here to get no GS, what are we going to do? Well, first of all, let's close this lip folder and here we are going to create a separate folder called server. Let me just rename it. And this server folder, we are going to do all of our tasks. So I'll right, click on this and open it and integrated terminal via the server folder here and make sure to always keep this terminal open so that we can migrate and do our task quickly. So now to initialize no J in our project, this is a flood project. And in year we have created a server folder, which will contain all the server files that we need. So here, what we need to do just to initialize node in our project, in the server folder, we can run NPM in it. And after we do that, NPM stands for node package manager. We look into that in a second, but while we initialize this, you can see it asks us for certain stuff. We don't have to enter any of this unless you want to change package name, which you're already familiar with.Even in fluter, you're familiar with package names. For example, if you go to the Android manifest file, you'll find the package name of our project aware. So we're familiar with that. So we want nothing different than the package name. It provides us by a default. So I'm just going to click on enter without entering anything. Then the version is going to be one I'm going to manually type enter. Then the description. I won't want to add any description I can click on enter. And the entry point, this is going to be index GS file. So entry point is basically whenever we start the server, it'll start by running this file, which is index GS, which we will have to create. I can click on enter because that's what I want. And then finally, I can click on enter for this, this, this, this, and this. And if this is okay for us, then we should type in nothing, but just press enter. And we have no installed in our, uh, server folder. And if we click away, you can see package Jason file. So what is this package or Jason file? This package do, Jason file is similar to the pop spec DOL file.It contains all the information about our application, like the name of it, the version, the description, the main, or the entry point of our project. Then the scripts we are going to make sure that we change it a bit, but this scripts will ensure that we can run terminal commands from here just to get this over started author license. And there's other thing called dependencies. When we install one of the dependencies, just like we do in spec do file over here. We have dependencies and we install them like HTTP module. Similar to that, we are going to install pair, package, uh, dependencies and package adjacent file Jason file. And we are going to have dev dependencies as well. Just like we have in pec do file. If you want to do integration testing or widget testing, you have to add dev dependencies. You have to add package adjacent, any developer dependencies that you need. And we are going to install dependencies with no package manager. As I said, we look into that in a bit, but for now, let's just write the first script in no JS. So here I'm going to create index or JS file. And in case you don't wanna name this index or JS file and change the entry point of your file, you can just edit it over and it'll make sure that this index or JS file doesn't run. But instead, what you've entered runs after having that, what we can do is just write console dot log, hello word. So this is the very first script that you're going to write. HelloWorld and console dot log basically means we are printing it out on the terminal. So this is similar to print HelloWorld in dot. So after saving it, what you need to do is run node. And then you can just pause in a full stop just to run this whole folder or otherwise you can mention the file you want to run. So no index Rogers, and you can see it prints out HelloWorld. So this is a very first script that we've written out and we are going to write much, much bigger scripts than this. All right, now you can see over your, we are using extension of GS. As I said, node is not a programming language. It is just a JavaScript environment and we are using JavaScript to write our code. All of the code is going to be in JavaScript, but you don't need to know any syntax for JavaScript.You just need to be clear with certain concepts, which is covered in dot. All right. Now, having understood how to write the very first script. NORS let's understand something about dependencies. So what are dependencies in NORS in fluter or in any other programming languages? Well, software dependency is an external standalone library that can be organized into packages to perform specific tasks. If you see over here, it's written search packages and the full form of MPM is not package manager. Not this, it keeps on changing. So with this NPM website, if you go on this link is mentioned in the description below. If you go over here, you'll see that we can search for packages and we'll install any of them. Just like we have pop.dev. You can see, we have NPM js.com with this. We can install any node package and over we can install any dot of letter package that we want. So you're, we are going to type in some packages that we are going to use. Well, first of all, let's just type in HTTP. You can see it gives us results of multiple HTTP packages. So here we have HTTP. This is the one we are going to use, and it gives a whole document of what is HTTP. Well, it is LA. It has published two years ago. It is public. This is a description. And then we, uh, it tells us how we can install this. So we have to do NPM I, which stands for install HTTP. Then it is a get repository. If you click over here, this is a code, then this is a homepage. Then these are the weekly downloads. So right now it is on one 46,000 and you can try and run it on rank it, but you're not going to do that. So to install this, so we are going to install HTTP later on, but for now, let's just ignore it. And now let's go to the another package that you're going to use, which is express. If you click over here, we have express. Now what is express? It's a, this is the package that our whole app is going to rely on. And you can see it is published nine days ago. We can install it using this. And there are these many weekly downloads, which is 21 million weekly downloads. And you can see the graph as well. So express is just a prebuilt, no, just framework that will help us in creating server side, web applications faster and even smarter.It's very simple and minimal. And since it's a package, it's going to reduce our workload and it's going to be really helpful for us. We are going to install this other package that we are going to use is mongoose. What is Mongo? Well, Mongo is a Mongo object modeling tool designed to work in an asynchronous environment. It provides both promises and callbacks. What now, before understanding what this means, we need to understand what are promises. Promises is a very complex topic in JavaScript for some people, but promises are basically like futures in data, nothing. I mean, there's a bit of difference, but the main idea is that it has to wait before. It can. The main idea for both of them, the promises and futures is that they don't have to wait for the asynchronous code to work and instead make other part of the code work so that there's no deal in the application. And this user doesn't face any difficulties. And we are going to use MongoDB. Now, what is MongoDB? Basically, it's a database. It is going to store all the data that we need. It's not like fire base. I mean, there are many, many more features and fire base as a whole, but it can be compared to fire based fire store. So we are gonna install that. So let's quickly install all of these three dependencies. So we'll do NPM install. Even this can work and even NPM, I can work. And then we need to install HTTP, express, and Mongo. You can write all of them in a single line without the need of comas, just a space and it'll install it. You don't have to go to the package, Jason, like you do in pop file and just add dependency tag over and pass in something like this.We don't need to do that. We just need to run this command and it will install for us. So if I click on enter, now you can see it has been installed again. If you don't have node, it won't work for you because it won't identify NPM kind of terminal input. And now if you go packaged adjacent, you can see dependencies over. There is express, HTTP and Mongos installed with the latest versions that you can see, which is 6.3 0.2. You Haveit then for express, you'll find the same in case you want to install dependencies with the same version you can do. What you can do is NPM install Mongo, for example, at 6.3 0.2, and it'll make sure Mongo is installed at that particular version. Now I've told to you about express, but now let me show you a quick syntax of express and how are we going to do that?So now after writing a first script node JS, let's quickly write a first API in node JS. So let me just quickly type in a comment for creating an API. And now, as I said, we are going to create an API and we are going to use node JS for it. Uh, and we're going to use express for it. So here I'm going to have constant express, which is equal to require express. Now, since this is an external package installed from a another website, which is NPM GS, usually you only need that. So we have required express. If you don't understand this text, it's similar to import line and flutter. Like we have import, let's say package express, express dot, dot. This is similar to this line in fluter all right, and you can name this. Anything you don't necessarily have to name it, express. If you want, you can just write your ABC and it'll require express for you in the form of ABC. Now you can use ABC to use express anywhere in your application, but since we are using express, and if the app gets larger, it'll be a problem. So let's write the correct names for it. Now we can take this express and now let's initialize express and save it in a variable. So we will have constant, let's say app, which will be equal to express. We are basically just initializing this and saving it in the app. Variable, nothing really great. And this is constant constant, meaning that the variable is never going to change because it's a constant. Now we can use this app and do app dot listen. So this app dot listen, basically binds itself with the host that we are going to specify and listen for any other connections. So now we have to pass in, first of all, the port. So let's create a variable right at the top so that, you know, it's visible to us. And in case we want to change it, we don't have to scroll down as, and when our app gets bigger. So you have constant port equal to 3000. You can mention any number, but 3000 is sort of like a convention. So we can just take that and we'll have port. Now, if we don't specify any other host name, aware, for example, any IP address. So it will access something known as local host, and we can access our own API using local host. Now, what is local host? So suppose you call an IP address on your computer. IP address is basically some random string that you'll find like 1 9, 2 0.991, something like that. You have seen that number on your computer multiple times. So whenever you call an IP address, you're trying to compute contact another computer on the internet. But when you call the IP address, like one twenty seven 0.0 0.0 0.1, then you're communicating with the local host. It means that the computer is talking to itself. So if we don't specify anything, it'll take in local host. Now we are going to specify an IP address, which is 0.0 0.0 0.0, which stands for it can be accessed from anywhere. So this is 0.0 0.0, and we need, and the reason we need to specify this IP address is because on Android simulators or even on Android devices, if we use local host, it won't work on, I simulators. It does work, but for some reason, Android is not able to take an local host. And instead we need to work using our own IP addresses just for debugging. When you deploy it to a website, then it'll make sure to give you a URL, which you can use.But for now, we are just going to pass in 0.0 0.0. After that we need a callback function. We are pretty familiar with the callback functions, and this is how we would create it. That because this is a Syntaxin do, but in JavaScript either you can have function over here because essentially it's a call back function or otherwise you can remove this and make it like an add or function. So this is also a function in do in Java script. Sorry. So you, you can do this or pass in function over, but not both at the same time. Otherwise it'll give you an error. And now just to see if it's connected to a port, what we can do is again, print it out, using console dot log. And then we can say connected at port plus whatever port that we have. And now this will work fine. So if I just run it again, using node index dos, you can see the server has started. It has printed out hello world, and it's listening to any connection requests that we will get now, as this works. Well, I don't want to, you know, have a plus sign where anywhere in my application, it's a pretty bad way of doing it in that we use string interation. So, you know, we have port like this and we, then we don't have to pass in the plus. Now you can't do this in do in JavaScript. Sorry. So to do it in JavaScript, what you need to do is enter back takeover, which is present below the escape key. And even here, now we have it. Now we can use this, but still it's not highlighting it to highlight it. You just need to pass in curly brackets. And there you have it. It's connected at port and it is going to return the same output. But now it's, it just looks cleaner. Now, if I exit my listen command and node index or, and run the index Rogers file again, you can see hello world and connected at port 3000. Now let's create our first API request. But before doing that, I want to introduce you with another dependency, which is a dev dependency. As you can see, after making some changes, I have to restart my whole server. So for example, I have to terminate this again, run it again, terminate this again, run it. So it's a lot of effort for us. What if we just make a minor change? For example, I want to add a space here and then maybe type in hello then just for this change, I have to run my terminal again. So instead of doing that, what we can do is add another dev dependency, which is <inaudible>. If I click over your and pass in node one, you can see your have node. One has published 10 days ago with 4 million weekly downloads. So we are going to install this. So we are going to have node one, sorry, NPM, install node one. And now we want this. I want it as a dev dependency. It's not anywhere in my application. For example, We are going to use express in our code, but you're not going to use node one anywhere in our code. It's just for our benefit as a developer. So what I'm going to do is pass in dash dash, save dev with this. It'll save it as a developer dependency. And now if I click on enter It, installs it for us. If you go to package adjacent, you can see, we have as a dev dependency node one, now that we have package Jason install, what we can do is node one. Instead of running node index JS, we are going to run node one index JS, and you can see when we run it, it is saying on node found node one. This is because we have to add an additional script for it. Node was installed in our system files, Norman isn't. So now what we need to do is go in the scripts and add a script. Well, the first script we are going to add is a dev dev script. And here we are going to pass in node dot slash index GS. Basically when we run this command dev, which is short for NPM run dev, which is your, when we, whenever we run NPM run dev, it'll make sure to run this command instead, and then it'll run the app for us. So I'm going to save this much and now run NPM run dev, and you can see. So I started and it's saying node one with the version number to restart anytime, enter RS. So if I just enter RS, it'll restart. But even if I make certain changes, for example, I type hello, and I save, you can see without me typing RS, whenever the file is saved, it'll make sure to restart our whole server. And now it'll also print the correct thing like hello. Now we don't have to manually exit the terminal and restart our server. And now, since you have added dev dependency, let's add for a start dependency. So whenever we run something like, let me close a terminal, something like NPM start. Then we need to make sure that we run node slash index JS. We are not going to need this during development or debugging, but during installation, but during deployment to the server, this is going to be of a great use. So let's exit this. And if I click on NPM start, you can see it has started node, but it has not started node more. I'll exit this clear of the terminal and run NPM run dev. Now we are listening to everything. So let's create an API finally. So we to create an API. Well, you might know that APIs have get request, put request, post request, delete and update, which is basically crude. Create, write, Create, read, update, delete. So let's create an API, forget request nothing much. We are going to look after post delete and update as well. But for now, let's look at get, because for post, there are certain things that we need to provide in case we want to see a great output. But now for now, what I want to do is whatever API that I create, I want to go there. It'll provide me with a link. I mean, the link will be our own IP address. So whenever we go to that link, since it's a get request, it's going to give us something right, because it is going to fetch some data. So whenever I go to that link, I need to see, let's say hello world again. So now what I'm going to do is app dot get, and that's it. That's how easy it is now, app dot get. And then we need to specify what path should it be? For example, how is our API going to look like? So for example, this is going to be HTTP, colon slash slash, then our IP address then slash now, if we do this much, you know, it'll create a slash API get request, but what do I want? I just want to have a part name of let's say hello world. So now I have to type in hello, world over, and then obviously a call function. And again, just to remind you, this is how we create functions in JavaScript. Otherwise you can just use the function keyword and remove this arrow symbol. And now this callback function is going to run. Whenever we reach this path on this IP address that we enter. So for now, let's just say, and here we are going to have request result. So with request, we can access anything that the user provides us with, for example, body or anything, but in get request, I don't think there's any body, but we have result. So what do we want to output on the screen? What do we want to send as a result? So what do we need to do? Well, we are going to send dress dot and you can see it provides us with a bunch of options for now. Let's use rest dot send. Otherwise you can use rest.Jason, the difference is that sends send will send it in a basic text format and Jason is going to send adjacent response, nothing new. We are going to use rest Jason throughout our application, but for now, just to demonstrate, I can use rest dot send and then pass in somebody. So for the body, what I'm going pass in. Hello? Well, and now this will give me an error because, well, we need to pass in something, right? It's not a number. We can send a number, but we're not passing in a number. We are passing in a string. And as we know it, just to pass in a string, we need to pass in double quotes or a single quote, anything. And now if I save this, you see it has been converted to double tick or double inverted comma. And that's because of the prettier format, prettier formatter in via code extension. So if you go to the extension tab and find prettier, you can see prettier code formatter and it'll format all our code. So you can install that. Now our API first ever API is created. It's not giving us any error. There are no syntax errors as of now. So what we can do is test our application, but to test our application, we have to specify our IP address, which we will do later on. But for now, since you're not testing on any simulator, I can just remove this IP address. We are going to add it back. Don't worry. But for now, just to demonstrate, I am going to go to the website with local host. So here I'm going to open Google Chrome and I'm going have local host and then pass in the port name, local host port name with a colon local host 3000 slash. Now, if I just do this much, you can see, cannot get slash. Now this is actually a great indication because it has finally said that it cannot get any slash request. That means a server is running. It is listening to API calls, but we have not created an API call for slash. Now let's specify the path name that we had hello world. And now if we do this much, it gives us hello word. And just to see what we will get. If we pass in Jason, then we need to pass in an object away. And what is the object going to be? Well, it's going to be named something like let's say hi, and we're going to call it. Hello word. Now, if I restart this, you can see, we are getting adjacent format with high as a key and hello world as a parameter. And I'm getting this formatted because of an extension that I'm using. If you click over here, I have the adjacent format at extension. You can download it. If you're on Chrome, I'm using the adjacent format extension. And that is why it's coming as a formatted string. Great. Now this is working now, what I want you to do as an exercise is create a get slash request. So without having to look at this code, just try to write it on your own with whatever you've understood. So this is your exercise. You can create a get request, giving adjacent response with key of name and value of your name. Basically, I want the format adjacent to look something like slash with the key as the name and the value as R for me, it's R because it's my name. You can pass in any name that you have. So I want you to have this kind of response. Were you able to do it? If not, then no problem. But if yes, congratulations, you've created your own re request or API on your own. So now just to demonstrate quickly, we are going to create an app dot, get which slash as a path and then a callback function, which would be request response. Then I'm just going to type in not console dot log, press dot Jason. And then the name is going to be Reon and save this much. Now, if I restart the browser, I'm getting Revan with the name property away. Great. Now let me remove the comments quickly.You can already see the problem over your as, and when we have more and more API requests, you can see with two, it feels clouded to me. So as, and when we get more and more API requests, for example, you have so many features in our application like authentication, admin sided features, products, user the home screen that we want to see the product details that we want to screen. The product that we want to add. There are going to be so many requests and all, and it's going to be very congested to put them in a single file. So to put them in different files, what are we going to do just to make our code look neater? And when there are multiple people working on it, it'll be a great relief for them. Nobody likes to see, you know, like a hundreds, like a hundred thousand line of code put together. And I'm not saying you're going to have that much code, but as if you want to extend this app, it go to that extent. So now what are we going to do well before doing that? Let's just remove all the unnecessary things. Now we are familiar with everything. Let me also remove these two get requests because we don't need that. And now our app is working great. So now how do we manage different requests? Now we can take this express, take this app, create this again, use this app dot listen in every file that we use. Now, this is going to be pretty hectic, and we need to run those files individually. We don't want that. We want, we just want to run this index or JS file, which will trigger, trigger all the other files. So for that, first of all, let's go to the server, create a routes folder where all our routes are going to be set up. Then we are going to create a file called let's say.gs, which is a very first file. And the functionality we are going to add in just five minutes or so. First of all, let's ex require express. I mean, that's the first thing we need to do, but we don't need any of this. All right, no, no express initialization or listening to anything. We are already listening it away. Now we are going to create a router. Now with this router, we'll be able to use that instead of this app instance or the express instance saved an app. So what I'm seeing is we are going to create an router. Let's name it, that, and we are going to require it from, and what is this router going to be? Well, we are going to use express for it, but we are not going to initialize it using express.Otherwise we'll have to listen. It, what we need to do is express router and this, with this, we have access to the express router and we can use or router now, instead of app. Now, instead of doing app dot a app looks better. So now, if I do app router dot get, you can see we're not getting any suggestions for it because dot router shouldn't be initialized like this. It's going to be a function. Your, we are just touring the address of this router in out router. We don't want that. We want to use the functionality ofout router. That's why we are going to now have parameters passed away here. So we are going to have app router dot get, and now we also get the auto complete. And after using throughout, do we can, let's say pass in slash user. Now we are, again, going to have request response. All of this doesn't change, and we are going to return, let's say, rest dot Jason message. And that's it. Now, if we go to slash user, we are not going to get anything. For example, if I via and pass in slash user, you can see, cannot get slash user. Even though we created a router away because this index or JS file doesn't know what this GS is or what it's doing, because we have not required it from anywhere. Index JS, basically doesn't even know its existence. So what do we need to do? Well, make sure it knows its existence, right? So what are we going to do require this all router? So what are we going to do? Well, let me add some comments, just to tell you this part is going to consist of all the imports from packages here. We are going to have imports from other files, and this is all the initializations I'm going to pass in as in it. So this is going to consist of all the initializations. Now let's import from other files. So we have constant or router equal to require. And now we are going to do relative importing, just like in fluter. We have to directly do fluter. Let's say package fluter slash we have let's say screens slash T dot file. We have to do something similar to this, but in case you've noticed one thing in flat you, what you can do, alternatively, is if you're in the lip folder, and let's say you're in the main door dot file, and you want to get S screen dot. What you can do is import dot slash features slash slash screens slash screen.dot. This is called relative importing. So you have to import, according to where you are in your project, we are going to do something similar in this because no J doesn't have the other type of importing or even JavaScript. So now we are going to have require, and we are going to require from, let me close the lift folder. And where are we? We are in the index or JS file. We want to get to the S file. So what are we going to do? Do slash route slash O and then you can pass in JS, but it's not mandatory. You can pass in as O and it'll recognize that you want the JS extension, and then we can save this much. Let's remove this comment, and now we have it now, still, we won't be able to access it. You can see, and it's not giving us any error, but this author router doesn't even exist for us because these are all private. You can consider them as private there. They can be used. This variable can be used only in this file, not outside this file to access it outside this file, we need to export this file or this variable to export this variable. What we need to do is module dot exports equal to or outer with this. Basically, you are telling that yeah, author outer is not just a private file. I mean, not a private variable. It can be used anywhere in the application So we can save this much. And now we have author outer, existing. I mean, still the API won't work because we need to do other configurations as well. We need to add something known as middleware now to understand the concept of middleware. Well, we need to understand what exactly are we going to achieve? Well, we have our client side, which is flatter. And from client side, they're going to send data to server side. And then with that server is going to return something to client side, because we are going to send rest Jason somewhere. So it's going to return something from the server side as well. And again, going to the client side and there it stops. It's not continuous listening because if you want to use continuous listening, we are going to use socket tile for that. It's not in this tutorial. You can check out my other tutorials, where I've used sock tile, which is real time communication. So here, as I was explaining, we have client and we're sending data to server. But what if I want to manipulate the data that we are sending? Suppose we send some data. We have a very large team and some person send some data. He doesn't know what format do we have to send it in? Well, we can specify that format using middleware. So this middleware is going to come in over your client, sends data to server, but this middleware is going to come in middle of client and server. And we can use anything that we want. So here we are going to have a middleware of app dot use. This is how you use middleware in no J applications. So what are we going to use or router? And now our, our index, JSR no JS application knows about the existence of, or router or this a JS file as a whole, because we are using or router everywhere in case you use something else. It won't know. And it won't use any of that, but we are going to use all router because that's what we are exporting you. In case you want to export multiple things, you have to create an object or a map in dart. So you, you have to create an object and then you have to pass in something else as that else that you want to access. For example, you want to pass in your name so you can pass a name like this and pass in R If you're wondering why we don't have to mention colon that's because it's a shorthand syntax. If I type away your or router, it'll do the same thing that it did earlier, but this is just the same way. If your key and your value variable is matching, you can use this shorthand syntax, but over, we don't have both of them matching. In case I stored this sort one in another variable, then this name can be used like this, but since we don't have this external variable, it won't do anything. All right, now let's just remove this object. And instead use all outer. We are going to use objects in somewhere in our application, but for not, we are just going to have all router. All right. Now, if I restart, you can see this site cannot be reached because we are, we are getting an error where cannot access app before initialization, as the error suggests, we have app initialization over here, but we are using middleware over here. So let's take this in it and put it at the top. And now connected at 3000, we are not getting any error and now let's restart the application. And here we have it message Ivan. Now after understanding middleware and all of that stuff, finally, we can dive in T JS file and create our sign up and login functionalities. So now let's just remove this or route or get request because we don't need that. And now create a post request. We need to add post because we need to post to our database. We are sending a post request from our client side so that we can sign up. So we have the slash API slash sign up route. It's good to have slash API over because we're going to have admin panel in our application as well. So whenever we use admin, admin functionality is going to be like slash admin slash whatever feature that we have or whatever API that we are creating.So we are putting slash API aware so that it's, you know, better to read on later on. Now I'm going to have Rick re and then create a callback function. We have done that already multiple times. After that, let's decide, what do we want to do? Well, first of all, we want to get the data from the client, right? Because we want the username, email, password, all of that. Then we need to post that data in database. If you look at it from top, these are the two things that we need to do. And then finally, the third thing is just to return that data to the user so that we can save that data in the client side as well, so that we don't have to, you know, manually do something or let the user know that yeah, we have successfully done our job. So now we need to get the data from the client. Now, how do we get data from client to get the data from the client? It's pretty simple just to demonstrate, I'm going to print this out. What you need to do is wreck dot body. As you might have seen in the client side as well. Whenever you want to pass data in a post request, you pass in a body and now to get the body we have to pass in direct dot body. If this isn't clear to you, when we go to the client side and pass in the body, you'll understand what this wreck dot body is. And I'll explain it to you again, later on. But basically from now for your, what we are telling is to get some data from direct dot body. And now, what do we want to do? We want to access certain things from reg dot body. Well, what is it going to be name, email, and password, because that's what we need to accept while signing up, right? We created those text fields. Now let's get them now, whatever we pass in reg dot body is going to be a map because let me just show it to you now itself. Otherwise it'll be impossible for me to explain it to you. So your, whenever we pass in the body from the client side, we are going to have something like name and then the name variable, or the name editing controller, text, whatever the function that we have. So we have to pass this name and let's put an inverted comma. This is what we are sending from the client side. And similar to that, we are going to have email And password given out as well. These are the three things that we are going to send. So now to access this map that we're going to send, we are using red dot body, but with red dot body, we are going to get this object. Now, this object, or a map in dart, we need to accept one of these, you know, uh, properties. So like we want names separately in a different variable email, in a different variable map password in a different variable. So now a shorthand for that in Java script is using cons, which is just a modifier. And then we pass in the curly brackets and then pass in whatever properties that we have name, email, and password. These are the properties and we pass in the same thing. So we have name, email, password equal to reg dot body. And now we have access to all of them, but make sure whenever we use this variable, we need to make sure these are matching with these keys or properties in our object. Otherwise it'll give us an error. So with this, we have access to name, email, and password. Now we got the data from the client. So let's remove that comment. Next thing is post that data and database. So for that, we need to, uh, get, we need to make connection to our database now to make connection to our database. Again, we'll have to go to index and here use mongoose with mongoose. As I told, it's going to help us with MongoDB functions. So let's just require this and then use that. So now we have to make some connections. So now here I can just type in connections and then I can have Mongo dot connect, and then it'll accept Ari, which we have to connect to our database. When we go there, we'll find that out. And then finally, we have to pass in a then function because as you can see, because this is a promise or a future, so we need to pass in dot. Then you have seen the syntax in dot and it's similar to that. Otherwise you can just use a weight as well, but since you are not in any function, any none of the function is asynchronous because you're not in any function we have to use dot then, and it'll give us some value. And then we need to make sure that we type it connection successful. And if you think there is any error anymore, you can just pass in catch, and then we can have E and then we can just print that out as well. So we have console log E if you want, you can just ignore this, but no problem. And here you can see, we are already getting an error. The I power meter to open your must be a string, got undefined and undefined. So undefined in Java script is basically the no value is assigned to any variable or an object before using it. So you, we have not assigned anything. That's why we are not getting any, uh, you know, we are getting this error. Now we need the URL and for URL, we need to go to the MongoDB website. So now let's go, go over there in our browser, we need to type in mongodb.com. Then we need to click on sign in, or you can click on drive free. Since I already have an account created, I'm not going to create it. The steps are fairly straightforward. It won't be much of an issue. So yeah, what we need to do is you can click on, sign up and then sign up with Google. The steps I had up already straightforward as I third. So no need to worry about it. I'm just going to click on login with Google and up and see you on the dashboard. All right. So here I am in my dashboard. After signing up, you should be on the same screen. Now, what we need to do is click over here on this dropdown and click on new project. And now we need to name a project for the project name. We are going to name it something like let's say, flatter, Amazon cl, and I'm just going to type tutorial as well so that I don't get confused later on. After that, if you want to add any member set permissions, you can do that. You can edit this later on as well. And now click create project. After that, we come to this page and after coming to this page, we need to click on build a database. And if you want, you can just pay it, but I'm just going to go with free option, then click on create, and then select the shared cluster, select the default things that it provides us with.And then click on create cluster after that. How would you like to authenticate your connection? So to authenticate a connection and while passing in the that we want aware we have to pass in some URL with the username and the password. So this is a very important step. So here, I'm going to pass in the username as Ivan, and then I'm not going to use the default that <inaudible> gives, but instead use my own password and then click on create user, make sure that whatever you pass in, you remember it later on, after that, we need to scroll down and you're enter the IP address that we want because you're not using local host anymore. We are using IP addresses. So we can just pass in 0.0 0.0 0.0. That means allow access from anywhere, then click on, add entry and then finish and close.And now we will go to our database, which is currently being created after which we will be able to get our URL. So let's wait for it to get completed. All right, so now our cluster is ready, aware. Let's click on connect, and then you can see the options here. Connect with MongoDB, shell, connect your application using Mongo DB's native drivers or using MongoDB compass. We are going to use Mongo DB's native drivers, and we don't have to install anything for that because no GS has been installed already in our systems. After that, it gives us a connection string. We can copy this, make sure to not use mine, because I'm going to any ways disable this project and then click on close and then use this URL elevator. So now I'm going to create a separate URL at the top in the, in it comment. And here I'm gonna have DB equal to, and then pass in the URL. After that here you can see there's my username. And then it asks me to enter my password. Let's remove this password and enter my own password. Instead. Also make sure to remove this angle brackets. It has caused multiple issues with me some many times. So here I'm going to pass. And 1, 2, 3, which was my password. Again, make sure to not copy this URL as I'm going to disable my project very soon after that, we can take this DB and pass it in over here, and then click on save here. You can see connected at port 3000 and connection successful. That means connection to our Mongo. DB has been made successfully. Great. Now let's just go to our cluster and in the database. So if you want to view the data, you have to go to this collections tab and here you can see since we don't have any data, it's not ask, it's not showing us any data, but you can see, we can load a sample data set or add my own data. We are going to do that dynamically using our code. So now let's get started with it. So whenever we are signing up, what are the validations that we need to do? You always have to keep that in mind. What validations can you perform before posting that data in the database? What other things that do we have to care about? For example, if you're fi using fire base, you can see fire base authentication, handles everything for us, be it that your password is six characters. So it'll give you an error like V password. And then it'll tell you that your password should at least be six characters. Then you don't need to worry about same account with email, same account with email password, something like this. You don't need to worry about them since at least authentication handles everything for us, but here we have to do all on our own manually. So we are introducing same account with email and password, that validation. So what do we need to check? Well, we wanna check if INR collections, if there is any user with the same email as ours, they can have the same name. They can have the same password as it, but they cannot have the same email. So to check that, first of all, we need to create our own model. If even if you're using flatter, it's always recommended to build your own models, right? In no JS. And while connecting to MongoDB, we always use Mongo. I mean, most of the people use mongoose. There are some people who do it manually, but I feel it's a, a great time saver for us. So here, I'm going to create a new folder called models. And I'm going to call this model. Let's say user dot JS, because that's a user model that we are creating. And here we are going to import Mongo and we don't need to require express or anything aware because we directly are creating a model lawyer. We are, we are having no interactions with express or with no, just APIs, just a structure of our code. So the very first thing we need to do is create a schema. Schema is basically like a structure of our application or the user model that we are going to have. So to create a new schema or a structure, we are going to do mongoose dot schema and then add a parent thesis after which we need to pass in an object like this. After that, we need to define some properties that are going to be in this model. And unlike dot, we don't have to specify types anywhere as you might have already seen. You're using cons everywhere. Even if, uh, we don't have to specify anything like string and all of that, because JavaScript is not a static type language. It's a dynamically type language. So let's define some properties. So we need name, and that's not how we are going to do it. Name comma. That's not how it's done. We need to specify more properties inside of this name. So we have the name property in the user model, but what is this name going to be like? What is, what is its type? So they're going to pass in a type as string. So even if the user enters name as some number, then we are able to identify, oh, he has entered a wrong thing. And as I said, Java script is a statically is a dynamic Java script is a dynamically type language. So here we are just passing in a type string for Mongo. We're not doing this for Java script or anything. This is all by Mongo because you can see, we are using Mongo schema. After that, we need to make sure that the user always enter their name. So we are to set name to true, and we can also set trim two. True. And you already know what trim means. If the user enters something like Reon, then it'll make sure to give us an output. Like Revan removing all the leading and trailing spaces. So we need to make that cleaning form formation, something like that. Then we need to pass in an email and you're again, you're going to have required. True type is going to be of the type spring. Again, trim will be set to true. And then there's additional property that we are going to add in email, which is validate or validate in this validate. As you might have seen in text form field. If you just go there custom text field, we have not added any validation here, but you can see that it validates everything. Even here, we are going to validate and for email, what are we going to validate? Well, we are just going to validate if it's matching with all criteria, like there's at the rate there's dot com. There's something like that. You know? So now how to validate, well, in the validate property, we need to pass in validate, which will return to us some value, obviously, and then it's going to be a function it's similar to the, this line is pretty similar to this line, but just in the same text of JavaScript.And then we need to ma match certain criterias. So what do we need to validate even custom text, form field. We are going to do something similar, not the, the validation logic that we are going to perform here, but something similar. So what do we need to validate? Well, as I said, you need to need to pass and add rate.com, everything like that. So for this, we are going to use something like rejects. So what is rejects? Rejects is going to be used somewhere in our application. Again, I'll point it out when we use it, but expression or RegX is a sequence of characters that specify a search pattern in a text. So if you go to this website, workflow.com, I've, I'll mention the link in the description below. And if you want, you can just search on Google validation for email address in JavaScript. And then it'll point out this website where you can copy this rejects. And if you don't even understand this, then it's no problem. You can just copy this, have constant R equal to whatever this is. All right, And you don't have to pass it in string because it's a REDX, it's not a string. And then you have to use value, which is this value. That is your, and we need to match this with the REDX. So if you just see over here, it says that matches, this function matches a string with a regular expression and returns an add containing the results of that search. So what this does is basically whatever value that you enter. Suppose I passed in Ravana, the gmail.com, then it'll match that value with the rejects that we specify. And if any of the criterias get filled, it'll return to us an a, so that's what we want to do. So we'll just do re re and then return this value because it needs to be returned. And now after that, we have another property where called message. And then this message property will be run whenever this validator is falls.That means only if the value over here, whatever we enter matches. Thiss, it'll tell us that this email is valid, and if it's not valid, then it'll return to us an error. And we'll say, please enter a valid email address. After that, we need to specify more properties. So we have email after that, we have password and we need to store password along with us, because this is not five base authentication. So for password, we are going to require it as true, and then pass in the type as string. Then we need address. We are just toing it right now. So address is going to be of the type string, but when we sign the user up, we are not going to store any address for them, right? So what are we going to do? Well, default it to an empty string address is not a required field. Whenever we create a user model,We don't want to pass in any address because we don't have an address at that point. And it's pretty stupid to, again and again, just type in an empty string. Instead, we can specify default layer and set it to an empty string. After that, we are going to specify the user type and this user type can be a seller or an admin. And in this app, it'll only be admin since we will be including only admin feature. We don't have any seller, but after following this tutorial, when you have enough knowledge, you can create the seller part of the app as well. So you're, I'm gonna have a type of string. And by default, we are going to set it to user because we don't want everyone to become an admin, right? So whenever the user just signs up, we don't want them to become a U an admin. So that's why we are specifying user aware with this type. We are going to perform multiple logic, uh, validations while transitioning to another screen. That's great. After that, we're going to have a property called card. And we look into that when we get to the card side of the things, but for now, let's not pass anything at all. Great. So after this user schema is done, obviously we need to export it because, well, first of all, this is a user schema, not a model. This is just a structure of how a user is going to look like we have not created a model yet. So to create a model, we need to first shave it in a variable, and we'll do mongoose dot model. With the help of model, we are able to specify the model name, which is user and then pass in the schema for our model, which is user schema.And after that, as we know, Java script will keep all these variables in one particular file, which can be used in one particular file. So we just use module dot exports equal to user great. After having that, we can go over. So here we are going to use user let's import that you can see constant user equal to require models slash user. And you can see double dots away. These double dots are basically like we are in this route slash art folder. So we need to get out of here. So we are in the main server folder. So we use double dot slash and then we go to the models folder, and then in the user file. Great. Now we have the user model available with us. So we just need to use user dot, find one. This is a property by Mongo itself. So here we are basically telling that we need to find a user, but which user do we need to find?Right? So here we are going to specify the properties. Well, we need to specify email property. So we need to do email email, but we know the shorthand, certain tax for this in JavaScript. So we can just remove this and we are, have user dot, find one email. So we have gone to our user collection. We are checking to find any one document in our user collection with the same email property. If it is there, then it will return to us an existing user. That means we need to stop our app execution right now and just tell, yeah, this email already exists. So one thing to note earlier is that find one is a promise. So, because we are using user dot, find one, it's going to the MongoDB database and then finding one document and it's going to take a lot of time. So it's going be an asynchronous process. So we have to mark this function, asynchronous, first of all, so that we can use a weight layer similar to data, right? So here we can pass in asynchronous over here in case you're using function, then you have some syntax like this, so you can use a secure as well. Both are fine. So we are gonna just make this asynchronous like this. And now we can use a weight to find one user. Otherwise it'll return to other promise, just like in that, if we don't use a weight, it'll return to, as a type of future right here, we would've gotten a, a promise and we can't access promise values. We need to update for us to, for it to return some value to us. So here we are going to have, if there's an existing user, now this will not give us a bullion value, but in JavaScript, it basically means that if existing user is already existing with this, we are just checking that if existing user is there, if this object that is going to return consists of anything. So here we are just checking. If existing user is there, then we are going to return Jason, and then pass in a message saying that the user would same email Already exists.Sweet. So it works. But now the problem is, and I can't show it to you right now, but just believe me for some time, as I'm saying this, you can see, we return rest. Jason value with the message user with same email already exists. Now, what is the problem over here? Even if we are getting an error over here, it'll return to us a status code of 200. So now the first question would be what are status codes? So if you go to this website, developer Moza link is mentioned in the description below. You can check all the status codes that, uh, occur when we use HTTP. So whenever we send an API request, these are the possible status codes that we can get. And since we are creating our own API, we have the ability to pass status codes like 200. So if we go by your successful responses, 200 means, okay, that, yeah, the request succeeded. So if you have get, it will just say the resource has been fetched and transmitted in the message body, but you're using post. That means the resource describing the result of action is transmitted in the message body. These are the parameters when 200 or okay, status is given. So your, if we don't specify anything by default, it'll think that, yeah, we have 200 status code, but that's not the case, right? Everything did not went well in our API. So here, what do we need to do is mention a status. So here we are gonna have status passed in. And then with this, we are going to change the status code that you're going to send. If we don't send any, it'll be 200, but we don't want to send 200. So that's why we are going to specify some other status. So just let's find out what status code is required. So you can see your, we have client error responses, or we have server error responses. Now, what is this message user with same email already exists. If the user with the same email is already existing, that means it's a client error, right?It's not anything that happened on the server. We are not responsible for it. That means we have to use something like 400. Now, what is this 400 request? It says bad request. The server cannot or will not process the request due to something that is perceived to be a client error. That's exactly the case. It's not 4 0 1. That means that the HTTP standard specify unauthorized. There's nothing like that. Even 4, 0, 2, even 4, 0 3. You can find out again and again, we have 4, 0 4 as well, which is the most famous one. So we are going to use 400. So let's specify 400 away. And there we have it. That's all that we need just to specify this and make sure to pass and return away. Because if we just specify something like this, it'll continue to execute the app further. We don't want to execute the app further.If the user has not already provided us with the email, then we just want to stop the app execution away, or the server execution away. That's why we are using return. And it'll return this status on this message. After that, if everything went well, that means our validation has completed. We don't need any other validation. For example, if password is six letters week, and if you want to add that, you can go and user.gs model and your pass in a validator. So your, you can just copy whatever we have done in email and make your own logic aware so that you can perform some validations. So for example, if you copy this, paste it away and then remove this rejects because we don't need rejects for this. And it's not mandatory to obviously put in validators again and again, I mean rejects again and again. So your, what do you need to check? Well, we just need to check if return value length. So whatever string that we're getting over here, it's obviously going to be of the type string since password is of the type string say value dot length is greater than six. So if value dot length is greater than six, that means it has been done successfully. Otherwise we need to specify that we need to enter a long password, right? But now I'm not going to validate this. And it's your exercise just to perform validations on any object that you think is really useful for you. So here, I'm now going to create a user model. So just like in that we will specify it. So we have user and then we have to use that and pass in an object. Now, as I'm using objects again and again, you'll be like, what the hell is he doing again? And again, objects. Well, it's like that only JavaScript is all objects. Everything in all, uh, Java script is an object. For example, spring is also an object. Everything that you can think of is an object in Java script. That's why I'm using object term continuously, just like in Florida, everything is a widget. Your everything is an object. Whatever you can think of is an object. So here, what are we going to specify? Well, first of all, you just can't create a user like this. You need to specify a new keyboard. So with this, we are creating a new user model and obviously we need to save it. So we will have constant user equal to new user. But later on, we are going to change this user's value with whatever data the MongoDB gave gives us after saving that. So what I I'm going to do, I'm going to make this let with let or VR. This is a keyword in.as well, but we're going to use lead because of some scope problems or scope functionality. So I'm going to use lead for this. You can even use VAR. It won't matter, but I'm more used to using lead. If you wanna know the differences, I'll mention the link in the description below. You can check it out in detail. So your, since I'm going to change this value, I'm sweating a tool letter. And now I have to specify some properties. So we need to specify email, then password and then name. It doesn't matter what order you pass it in. You just need to specify the required arguments. And for us, if we go to the user model, you can see name is required. Email is required. Password is required. Rest of the things are not required. Great. Now we have the user model. So what we need to do well, we will just use user equal to user do. You can see we have save wire, but now the problem is, again, we are using MongoDB to save it. So we are going to use a ware and now it looks great. So whenever we save some data, you might have seen that we are storing these three data along with some default, like empty address and empty type or user type. It'll give us more, two fields for version and ID ID is going to be the unique ID of your document, which is pretty cool. Even in fire based fire store, we have our unique identifier for every document that we create and version is the number of times we are going to edit that file. And how many times have we done that? It's not really useful for us, but it gives us that. And then we need to make sure that we send the data to the client side so we can just pass in user. And we're not PA passing in something like this, because user is again the same thing that I told you. You can either specify like this, or you can just specify user. And now we don't need to worry about the status code away. Just like we did aware because my default is going to be 200 and we want to send 200, right? Because the user has been created. All of our tasks have been doing successfully.Now let's test our application. So now you to test our APIs, we can use something known as postman. So if you go to this website, postman.com, you'll see that we can test APIs, debug them. And over 20 million developers are already using postman it's and it's a great tool for, uh, people building big, big application. It's always recommended to use postal, but what I'm going to do in this tutorial is use a built in vs code extension known as thunder client. So we have thunder client, you can see lightweight rest API client for vs code. It's similar to postman, but postman has a lot more features and it's very organized for big projects. But what I like to do is just have a built in thing in vs code. Again, it's similar to that. So if you want, uh, it's similar to thunder client. So if you want, you can just install that I would highly recommend using this. It's a very great tool, but for the, this tutorial and for the simplicity of it, I'm just going to use thunder client. So install it. I already have it installed. So after installing it, you'll see this tab over, which is this thunder client extension. Now you can click on new request over and then you can see it opens up a new file for us. And here we can pass in something. So we have the type of the request that we want to send. And by type I'll explain to you what I mean in just a bit, but over here, you can see, we have 30 parameters that we can pass in headers or anything, body. We are going to use this extensively and any tests that we wanna perform, we're not going to use this or this anywhere in our application for testing APIs, but you can do that. Postman has a lot more features than this. So if you want, you just download it. So now let me go to my file again. And you're in odd Rogers. We have this slash API slash signup. Now let's pass in the URL. So we have HTTP colon slash slash, and then we can pass in local host for now later on, we're going to use our own API or our own IP address. Sorry. So we are going to replace this with IP address everywhere, local host. Instead of that, we are going to specify our own IP address by fetching that, but only in the client side, in the server side, we are always going to use local host because I don't want to show you my IP. And it'll be difficult for me to blur this out as when I scroll it up. So here I need to pass in the parts. So we have slash API slash signup. And then if we click on, send, it should give us an error.And it has given us an error cannot get slash API slash signup. Now, the thing about the type of the request is that get request on this same URL is different from the post request on this URL. So you can have two URLs. For example, you can have two APIs created of the same URL URL, but just the difference in get request. So if you have getaway it's different from this router post API, that's the thing I needed to mention. If you get any kind of error like this, and you've already created your API, first of all, make sure that you've exported that and used it in the middleware, and then make sure that the correct type is given your, and your sweet. Now, if I send this, you can see connection was possibly closed by a peer. Again, we are going to click on send, and you can see connection was refused by the server.Now in the body, we need to pass in some Jason content. You can use example, text anything, but you know, we are going to use Jason because that's pretty easy. And if you don't know, Jason stands for JavaScript object notation, which is just a data exchange format to use text, to store and transmit objects. So now I'm going to pass in email and if you use single ware, it is definitely going to give you an error. So what do you need to do is use double inverted comas. If you use double inverted, it won't give you any error, but if you use single text. It'll give you an error. So here we need to pass in name and then pass in a test claim for now. So let's say R then pass in an email and again, pass in an email, let's say R and I'm going pass in R for now, just to see if ours in our user or JS file is working or not. After that, we need to click over here again and then pass in a password. And now we have test 1, 2, 3, and now when I click on send, you can see, we are getting this error, cannot destructure property name of reg dot body as it is undefined. And now this error is mainly because you can see where in the order just we have used destructuring. This is called destructuring that we are continuously using, and this destructuring can only be used on, on objects. So just your resolve, this error. What we need to do is add another middleware. So you can use app dot use and then pass and express dot Jason. With this, you can see it returns a middleware that only passes Jason and only looks at request where the content type head matches a type option. If you don't understand this, it basically passes incoming requests with Jason payloads.That's all it does here in file. Now, if I, we have restarted the server, so now let me just quickly save the file and again, restart it. And here. Now, if I send it, you can see we, if you're getting an error and this error is because you can see user validation has failed. That means our email properties is now working, but you can see it gives kind of a very bad error to us, you know, and if your client, we don't want to see any of that. So what I'm going to do is wrap it with a, try a catch block, and that's exactly what we should do whenever we use any asynchronous calls in our code. So let me quickly take this. I'll remove this from here, because we have posted the data and got the data as well, and now use a catch block away And send it over. So now res dot, we need to specify some status. And now for the sta the status for this is going to be 500. So if you go to that website again, you can see over here that server error responses are from 500 to 5 99. If I click over your, you can see 500 means an internal server error. That means that the server has encountered a situation. It does not know how to handle 5, 0 1 means not implemented, and you can see all of that. But for this tutorial, we are always going to use 500 for this catch error and just passing do Jason. And then we are passing an error over year, along with E dot message. Now, you might have noticed I've used message over year and error over here, and that's plainly because whenever we have some validation issue, we are going to use message for that, for that. And whenever we have some server error, then we're going to use error for that. It'll be a lot, much easier when we go on the client side and see why we are using what we are using over here. For example, when we have error via we using error over. So now if I click on new request again and click on send, you can see we have an error that the user validation fail email, please enter a valid email address. Great. That's exactly what we needed. So now I'm going, I can enter an email of dev gmail.com and then click send. You can see we are getting this data, and this is the data that we get away here. User is equal to avoid user dot say, and then we are sending it away. So we have this status 200, okay. And here we have the name, email password address type, and the ID of the user, which is symbolized using underscore ID. And then we have the version with dot, with underscore underscore version, which is zero for now. But if we update this, it'll become one, then two, then three. And so on. Now, if we go to the MongoDB website and just click on refresh away, you can see my first database has now a user and the user is <inaudible> with email, password address and type, but still, you can see that the password away is plainly word over here is plainly plainly.Given what if my password, what if my database account or my database data is getting hacked? So the user will get the password plainly and all of our users will lose their data and thus, it will get some errors. And that's not a pretty good thing. So here, what are we going to do is before saving the data to MongoDB, we are going to save this password. So how are we going to go about making sure that it's more secure? Well, we are just going to take this password and hash it. We are going to encrypt that password so that even if the data gets stolen by mistake, or, you know, there's some error from our side and then the hacker just gets used of the password. It'll be useful for him because the password is encrypted. So exactly for this purpose, we are going to make use of a package called B JS.So if you come to the NPM js.com website, you have B JS. And now if you're wondering, why aren't we doing this and five base and all of that fire base handles all of it within itself. And it doesn't give us that complexity, but aware we need to everything on our own, because this is our server. So we, we have BCR and we don't want BCR. We want BCR JS. So let's again, type it. Now we have BCR JS. So this is optimized, BCR and JavaScript with zero dependencies. And it has 1.2 million weekly downloads. And you can read more about it, aware all of that is given away. If you can read that and implement your own hashing, then it's pretty good. I would advise you to do that. And if you're not able to do it, at least try it. And if you're not able to do it, then you can follow along. So now let's just copy this command, stop our server page, this command, and then click on enter. Let's get rid of this request for now and your, we have the password. So this is where we need to implement. So now first things first, we need to import, we can import BCR JS. So we have B GS, which is equal to require B JS. Now we can take this BCR JS and what do we need to do? Well, we need to hash our password. So we have B JS dot hash. You can see this function error. You can explore multiple functions in your own playground file or anything like that. But we have, we are going to use hash with the help of the hash function. We are going to basically convert whatever string that we pass in a wire, which is the password string, and we are going to hash it. And then we are going to hash it. And then we need to provide a salt wire, which is it. Now, what is salt? Salt is a random string. And when we hash a text, for example, this password, we add a salt to it. And with this salt, the hash algorithms output is no longer predictable to us just to get your doubts. Cleared. Eight is not the link of the string that it should have. It's going to be much bigger than this. So the same password with no longer yield, the same hash, the salt that we pass away gets automatically included with our strings so that we don't have to store that salt in our, in our database as well via. So here, we just need to use the password that this hash functions give us. You can see it's a promise of the type string again. So what we can do is avoid this and store it in a new variable. And for that, we're going to use hashed password. And it's going to be a constant because you're not going to change these hashed passwords anytime.And now we have to pass that instead of hash password. So yeah, we could have passed in like this, but that means we are using something like this of a notation. And if you see in our user model and just scroll it up, this other type password, not hashed password. So instead of hash passing in hashed password, what you need to pass in is a password. Something like this. Now we have hashed a password. So let me start the server again. We are using a get request, so let's change it to post again, enter a body. I think I deleted my previous request, so we need to type it. You can use it again, but yeah, we have, let's do a different name this time as to Naman. Then we have email, as let's say, Naman, gmail.com, then we can use password. And the password is going to be test 1, 2, 3, and you can also not add this trailing adjacent format. So let's just remove this. And now if you click on send, you can see it got sent, but now the password is very different. It has hashed this password and it's more secure. So even if some hacker gets in between and steal that data, he will get a password that he won't understand. Great. So we have our sign of proud created with all the validation and logic. This was our sign of proud. Let's go to our client side now and connect this sign up API request with our client side. But before doing that, we again need to make sure that we pass in the IP address as 0.0 0.0 0.0 via. All right, because I forgot to remove that. I mean, obviously you can use local host with this IP address passed in as well, but it's usually nice when you have this IP address and you're using the IP address. Basically you can use local host no matter what, having created the API. Now let's go to the odd screen and now connect this API to our UI part so that we can start accessing it here. I'm going to work in the services folder so that our business logic is separated from a UI files and all that related stuff. So here I'm going to create service dot file. Then create a class for it called odd service. And now we are going to create a function for signing up the user. Since in this odd service, we are going to have another feature or another function for signing up the user for getting user data. All of the authentication part services are going to be in this. So the very first function that we're going to create is sign up user. Now this isn't going to return anything. So I'll just put an avoid and then call it, sign up user. Now we want to require certain things which is email Password, and then the name, these are the three things that we want. And later on, I think we, we will also need the build function because not build function, sorry, we will need the build context so that if there is any error, we can show the error in the form of a snag bar or something for now. Let's just give that. And now this is going to be an asynchronous process. We already know that because we are going to make some HTTP calls and HTTP will give us future. Now we are the TRICA block. And now in the tri block, well, first of all, let's create a user for this. So now we are going to create a model for the model. We are going to go in the lip folder and here create a model'sFolder and then call the file user dot file. This user dot file is containing the structure of our user. Just like we had something with Mongo, we are going to have this user model. So that later on, we can create a provider based on this user, because we'll be using state. Uh, we'll be using provider as a state management tool. If you're using any other state management tool, you can obviously go along with it, as long as you know how to convert provider to any other, you know, state management tool, whatever I'm doing right now. Sweet. So now let's create a class user and it's going to have the same properties as this user file. So let's create this class user, we'll make all the variables final. So we'll have final string ID and this ID, we don't have it in the user JS file or the user JS schema. And that's mainly because Mongo or MongoDB auto generates it for us, but here we are going to have an ID. After that, we will have a name. Then we're going to have a password. Then <affirmative> then an address, Then a type, which is a type of the user we've already created that you can see over here. And I think that's all that we need for now. Actually, we will need another type as well, which we will discuss about in just a while when we go to the sign and route. So let's create it right now, which is token and the card property that I told in the user dot file as well. We have this card comment. We'll add that later on, but for now, let's have all these things token you can just ignore for. Now. We will jump into that in a bit. So now I'm clicking on this bell I icon, or the be VI and then calling generate construction. After this, I can again, click on this bell VI and generate Jason serialization. We have all of this stuff after that, over here, you can see ID is map ID, but whenever we store the user, for example, let me go to my request over here.I'll send one and you can see user with same email address existed. Let's create one more and you can see, we have ID with underscore ID as the name over and with this from map, we are basically giving it a map later on. We will give it a map, which will be the object that we get in this request. We'll pass in this using user dot from map. And when we use this, it'll take in map at ID. Now map at ID is not available because this is of the type underscore ID it. For example, we have name aware, so it'll get this name. We have email. So we will get this email password, this password, but for ID, we have underscore ID. So let's put an underscore ID for you. If we put underscore ID over here, that would mean that this property is private in this class.We can't do do that in flutter, right? That's why we are using map underscore idea. I think these many functions are fine for now. So let's save this much, go via and create a user model. So we'll call this user. Let's import it at the top as well. So we have user user equal to user, and then we need to pass in all of this stuff, but we don't have any of this. I mean, except name, password, and email, we don't have anything. So we can just put them as an empty string. We'll fill that later on for address as well, type as well. You can pass a user. Also. It doesn't really matter. And for token as well, now we can save this much after this. What we need to do is use HTTP. And this is the plugin HTTP. You can use that it's by provided by Google itself. So we can just copy this using our dot dependency. We can just add this. And if you specify like this, also, it's not a thing it will just add in, but I'll just type in like this. So our flatter pub get is running great. Now we have access to HTTP module. So let's right at the top, we will have import HTTP, http.as HTTP, and as the name suggests, it will allow us to make API request to this URL. And now we have, we are using all of the functions at HTTP dot provides us with using the prefix HTTP. If we don't use HTTP, prefix, it'll cost confusions like this. If I just do get, you can see, we are getting the get request, which is from HTTP dot, but it's really confusing. So we are going to use the as HTTP prefix. Now we can use this HTTP and now we have http.post because this URL, if we just go over here, we have the post URL that we have created, and then we need to pass in the URL. Now for URL, as I told, local OS 3000 will work on is simulators, but not on Android once. So now to make this work for Android, what we have to do is go to our global variable and here just above the class of global variables, because if we put it in class, we'll have to make it static and then use global variables everywhere. I don't want that to happen. So I'm just creating a global variable called URL. So here I'm gonna string equal to this, and now is going to consist of our IP address with the port. So instead of having local host this, so let's just copy this. Instead of having local host of, we are just going to replace this with our IP address, to get your IP address on Mac, you can run the command if net config, or you can just search up on net. If you're on any other operating system, you can just find it on your own and then add it away. I'm going to paste mine because I don't want to show you the IP address. And it's always good to protect your IP addresses and not show it to everyone. Uh, so I've added my own IP address, make sure it's correct. And you know, it will work later on if it's not working, then there's some issue over there. So make sure it's correct. So having that, I can just use URI, which I'll import from global variables or dot file. And I can use it like this without having the need to use global variables dot because it's a global variable right now having URI. I want to convert it to a string. So I use string interpolation because I need, I've only added local host 3000 slash not even slash just local host 3000. We need to add rest of this, right? So let's just copy this much and paste it over here. So we have local, which is our IP address slash API slash signup, which is our http.post request. And you will see this error because it doesn't accept the type string. It accepts the type. So we need to convert the string Tori. So to convert it, Tori, we can use URI dot pass and then pass in this string. So your I'm going to replace this. You arrive with this and make you sure to add the slash away because we have just used local host or IP address 3000, not the rest of the thing. Great. Now, after that, we need to add a body. And if you go back to our JS file, you can see in the body, we are passing in name, email and password, because as I said, reg dot body, and now it's getting clear right here. We have the body tag and in body, we need to add something. And now in the body, we are adding this name, email, and password, and we are accepting it using rec. So we have request dot body and then we can access all of these by object destructuring. So now for the body, we can manually add using this and just encoding this in adjacent format, because we added a middleware. If we just go to our index or GS five, you can see we added a middleware of express adjacent so that it only uses Jason. So whatever string that we provide over a layer or map that we provide, we need to convert it to Jason. So we can use Jason in code for that, but we don't need to do all of that because we've created a user model for that sole purpose. So that there's chances of less error of, you know, typing. So we can just copy this user and use user dot two Jason method that we have created just now. And if we just go to the two Jason method, you can see it uses Jason dot NCOR calls, the two map function. And this is a two map function. And it'll return this object. We are basically doing what I told you earlier, but in a cleaner format, so that there's less of errors, you know, and in the user, I just realized in the user model, we have not added email. So below name, I'll just add final string email, and now you have to add it everywhere. Now, again, a shortcut for this is just to generate a constructor, then generate adjacent serialization, and we are good to go. It's as quick as it gets now, we need to add an email property away. So let's add email and we have the email from our parameters named parameters. Now we've posted this now, since we've used express Jason aware in our service, what we need to do to make some changes is use head away. And now this is going to be of the type string or string. So let's add string or string and then pass in the content type, which will be content type as a header. And it's necessary to add this just because of this express or Jason life, but it also makes a life much, much easier, right? So we have, if application slash Jason char said equal to UTF eight, if you don't understand this line, it's not a big deal. You can just copy paste this every time we use that, but we are going to use it every time when we make some requests now to our own API. And now let's just store this in a variable. You can always use dot then or a cleaner way of doing it is using a weight and store it in a variable. Now, what is this? A variable response? So let's have a response response equal to this. And now it automatically adds a prefix of HTTP because we are using a response from HTTP module.And now, after getting this rest variable, you can see, we can print it out. We have rest body to access, whatever data is there inside of this. Otherwise you can also access status code. The ones that we mentioned, like having 200, 500, 400, all of that. And we are going to make use of both of these very much in our application. So now we need to do error handling. You can see where we have added a TRICA blog, but that's not enough because this is variable. We are sending some stuff, right? If we just to go back on in the odds or GS file, you can see we are sending the data. So when it's 200, that means it's success. But when it's 500, there is an error we need to catch this error. Tri catch block is not going to catch those errors, right? We are standing that data. And whenever we get away your, the response variable, it thinks that yeah, it has center response. There's no error for this. So it's not going to get caught in the catch block. And the same for this message that we have, we need to catch this as well. So now what we can do is constantly, we are going to make use of this 400 and 500. So what we can do is in constants, we can create error handling, let's say error handling dot file. So yeah, we are gonna have an HTTP error handle function. And then we are going to require HTTP response. So we will have HTTP and let's import the HTTP module. So let's go over here, have HTTP and pass it to Ania. Then we can have HTTP dot response. Then we will need a build context so that we can display the snack bar. And then we will need a avoid callback function. Now this word callback is basically function like this wide callback is basically a short form for this. You can understand it that way, and then we can have on success. So what do we do when there's success? Right? Because everything will differ for every request. We are going to use this. So every time we send a request, let's say we are sending now for sign in. We are going to do for, we are sending for signup. We are going to do it for sign in as well. And we are going to use it throughout our application whenever we send responses or requests. So the success part is going to differ continuously. So that's why we are accepting that from the function as well. All right, so now we will have switch. And in the switch part, we will have response dot status code based on status codes. We are judging if we are having the error part or we are having some warning or something like that. So first case that we have is 200 when there's 200, that means it's, it is success. So we are going to run on success command. After that, we can break After that we have 400 and then we can run the shown bar. And now we need to create the show snack bar utility function. So what is the show snack bar going to do? So just show snack bar is continuously going to display whatever images, sorry, whatever text that we want. So you're in the constant part. We are going to create that as well. And here we are gonna have void show, snack bar, build context, pass in the string of text because every where the text is going to defer. So that's what we have. And now we are in a scaffold messenger context dot shown bar, just to avoid a lot of boiler plate code writing, just to show a snag bar, we are using this utility function, and now we can return a text which will display a text. Now we can take the show, snack bar, display it over here. And now pass in the text. The text is going to be what, when there's 400, we want to display response dot body at let's say message. Because if we just go to the odd GS file, you can see, we have the message property away when we are giving a status of 400. So yeah, we have it. And now you can see argument type string. Can't be assigned to parameter type end time. This is basically coming because this is response body. And we need to decode this Jason file that we have. So here we will just have Jason decode pass this response body, and then we can access the message property on it. Every time we get response body, we need to decode this because this is not a spring. This is Jason. I mean, it is a string for us in dot and flatter, but this is actually a Jason format. So we need to decode this Jason so that we can use it later on. And now we can again, break it. And finally, we will have case 500 and it <affirmative>, and it's going to be something similar to the show snack bar. So we can just copy that Paste it. And this here is going to be error, not message. Then we are going to break it and then pass in or default. So any of the status codes doesn't match, what are we going to show? Well, we are just going to show a snack bar where it's going to show response, do body. So let's just remove Jason dot decor so that it can entirely show the Jason format only because it's very rare when this will go any other way, because our API is always giving these three status codes. Now we can use this HTTP error handling everywhere. It's very clean to do it this way, in my opinion. So here we have H G DP error handle passing the response. So the response is rest the context, which is context, and now we need that context. So let's require it at the top. Great. Now, after having that, we need an on success function. So whenever a function is success, I mean, we get a 200 status code. What do we need to show? Well, in our application, you might have seen in the early starting one minute video, uh, one minute part that we need to basically show a snack bar. Whenever we have a success saying that account has been created and we need to log in with the same credentials. So if we come back to our application, see we have to enter name, email password. After clicking on, sign up, we have to go to the sign and route and then sign in with those validations and then we'll get signed in. So here we just need to display login with the same credentials. And here again, we will show a snack bar in case there's any error while sending a request. So we have this error and now we can just type in E dot two string, whatever we get away.Great. So we, our signup user function created as well. So we can just bind the signup user with our UI. So we can go to the odd screen and your create an instance of our function. So we will have final, sorry for our class, which will be so service. And we'll call that service equal to service And save it in the odd service variable. So we can just copy it from the top and paste it away. Now we can take this service, create a function away called wide signup user, then use or service dot signup user pass in the build context. And there's no need of using build context from your, because we are in the state full visit. And then we have email. So email is going to be email controller dot text, and there's no need to trim this because later on our Mongo class is trimming it, then we need to do password. So we'll have password controller, text, and then the name. So that will be name controller, text, and that's all that we need. It's not going to return anything since it's voided. So we can just take the signup user and bind it whenever we click on the signup user button. So we are Also here. We can see we are in a form right now. We need to make some validations, which we left earlier. Basically we are in this custom button, we are in a form. Our parent is a form and we have a key and every custom text failure has a validator. If we go away and we need to add this validator, which we will add just right now. So yeah, we just need to make this validations happen. Actually let's create the validator just now. So we have validator and in this validator, let's validate first of all, so, well, custom text feel is going to have the same validations everywhere, for example, where the value that we get, and it's very similar to Mongo that reader. So we have value. So here, the value can be nullable. So first we wanna check if value is equal to Nu. So if the value is equal to Nu or the value is empty, so we will have value is empty, then we need to return a text that says, enter your, and what do we need to enter? Well, enter your he text, right? Because we are passing in email for the he text password for the he text. So we just want to say, enter your hint text. So we'll have enter your email, enter your password, all of that. And then we're to return now. So either return enter your field or return because there are no errors. So a validation is successful. That means we need to return now. And now we are, we need to make sure that every text field that we have in this signup form gets validated. So we'll have F signup form, key dot current state, and it's nullable. So we can just have an exclamation mark dot validate. So we want to validate it right now, software validating. It'll give us a bullion value. You can see so that we can put it an if condition. So if validation goes, well, it'll say true. So we can follow along with our functions. That means our form has been validated. Otherwise it'll throw us an error on the screen itself. So yeah, we'll pass in, sign up user. And which is this function that we just created after saving this let's run our app. So we will run without debugging. I've selected iPhone pro simulator, and let's wait for our app to launch. All right? So our app has launched and here we can see we have that. And this is basically coming because this is the demo app. So here we have that and now let's pass in the name. So we will have Ivan and not enter the email, just to see if it's validating and pass in the password as test one to three, click on signup.You can see enter your email, which is a hand text away knowledge pass in test 1, 2, 3, age, email.com. Then click on signup account, created log in with the same credential and to, and to verify this, we can go to our MongoDB database and here you can see test 1, 2, 3 gmail.com with the password and the type as user, everything got saved. And now just to verify, we are receiving the right messages. Let me just remain, remove this. We'll just pass and test one to three.com. You can see user validation, fill email, please enter a valid email address. And that's exactly the message that we've given. So that's pretty cool. Now let's now having that in place and we've understood the sign apart. Let's quickly do the same thing. Similar thing for sign in now, what do we want to do when we sign in? Right? So when we sign in, we have these credentials past in. So now we click on sign in. We want to make sure that we get something known as JWT. So now let's close all the saved files so that it looks cleaner for us. Let's close the terminal as well, and now go to our GS file so that we can create a sign in route. So let's, uh, create a sign in route and now let's do it as an exercise. If you want, we can have exercise. So basically what we need to do is create the sign in route, but for that, you'll have to open the documentation for Jason web token and understand how it works. I'll just tell you the basic working, basically this Jason web token is going to make sure that we are who we say we are. So while sending some data, which has to be authenticated data. So for suppose, we need to get the user data. Only authenticated users can do that, but we need to make sure that we, the user is who they say they are. So Jason web can, is basically going to help us with that. They're going to let us verify that the content that we have have not been tampered with whatever data that we are going to sign it with are not tampered with, to know more about this. You can just Google it online and make sure to download this Jason web token package and implement it on your own. It'll be a great, great task for you, but in case you are not able to do it, then don't worry. You can just follow along. Well, it's going to be a post request just like this, because it's going to sign up, sign in. We'll have to use BCR JS again, because the password that we have, for example, we have the hash password, and then we need to find a user with that same email. So we get the password. But the password that we get will be a hashed password because you're storing hashed password. So we need to use B JS again, to compare the password that we have in the string format, because whatever the user enters away is going to be plain, test 1, 2, 3, but whatever the user has on the MongoDB database is hashed. So we need to make sure that we can use hashing and we can compare both of them. So you can refer to the B of JS documentation as well. But in case you're not able to do it, we will do it together. Now, were you able to do it? If not, let's do it along. And if yes, then great job. We can just verify if we are on the same page. So now we are going to create a post. We are going to slash API slash sign in. Then we can have asynchronous function. We will get request and response. And we have basically created our boiler plate. And now we also need a TRICA block because it's an asynchronous function. And now in theCatch block, we can just send stress status 500 Jason error E message. Yeah, we have it similar to this line after that. Yeah, we are going to get the email and password from reg dot body. So we have email password equal to reg dot body. Now we have a basic understanding of how this reg dot body is going to work with our client side. After that we are going to find the user, right? Yeah. We will have to find the user because we need, need to get the user data. So first of all, we need to check if that user even exists with that email. So we will have constant user equal to innovate user, which was our user model created using mongoose. And as you saw in our file away, we are find one option. We are going to use the same thing again away. So we will user dot find one. And we are going to find by the email, and then we can again, pass an email, but we knew the shorthand syntax. We can just use this after that. We can check if we get no user, I've explained this to you as well. This is not like dot. This is not a bullion value. This consists of user data, but in case this user data is null or undefined, then it'll give us a true value. Otherwise it'll give us a fall value. So if there's no user data, then we need to return arrest that says with a 400, obviously, because it's a bad request. So we will have Jason saying that this is a message and user with this email does not exist. Great. After that, we have to get to the good stuff after this, we have performed this validation.That means the user has an email and this email already exists. That means the user is signed up after this. We need to make sure that the password that the user has entered is matching or not. And as I said, we're going to use B for that again, because the password that we have is test 1, 2, 3, but the one that we are stored in the database is something gibberish. So let's just type in gibberish. So how can we compare both of them? Well, um, a very simple thing to do is using BCR JS inbuilt function called compare with this compare, it will say synchronously compares the given data against the given hash, exactly what we want. So we have to pass in password, which is a password from body. And then the second argument should be the hash hashed password. And the hashed password is going to be in the user object, which is called user dot password. And now this is going to be a promise. So we can ADE this and store. It is in a variable call Isma, which basically suggests because compar will give us a bullion value. You can see where it's, it is a bullion value, true or false value. So if it is matching, then it'll give us true. Otherwise it will give us false. So if is match, is there, then we want to proceed forward. But in case, if it's not there, so you love is match. And in case you're wondering why I'm using like this, putting a negation sign away and then passing in the data. This is called guard clauses. It helps in a writing better and you know, a readable code instead of writing nested AFLs. If conditions, we can just use a negation and use guard clauses for that. So you you're going to return a similar message. So let's just copy this message based in Ania. And you're going to send, send a message with saying incorrect password. Great. Now this is matching as well. So if it's not matching, then we are saying it's an incorrect password. And just one thing that I forgot to tell you about this crypto js.com, the first approach that you would've thought of is just converting this password into hash, using this B JS dot hash, and then comparing that hashed password along with this pass, sorry, user password that we have now, that way won't work because of this sold feature that I told you, it adds a random string. So no two passwords are exact same thing. It is going to add a random salt, and that will change the whole password. So two passwords, which are same, are not going to have the same hashed password. That's the thing to note.So you are now we will have now JWT used. So let's use the Jason web token. Let's install it first. So let's take this, copy this, go to our terminal in the terminal. We'll just exit our server for now and install this. So we will have NPM I, Jason, web token, click on enter after having that installs, let's clear it and run our server again, using NPM run dev, and let's use Jason web token at the top. So we will have constant JWT, which is it for short. So we can name this anything as long as a required part is using the correct name. So vLab Jason web token. Now we can take this JWT. So vLab JWT, and it provides us with a function called sign.As you can see, it tells that it secretly signs the given payload into adjacent web string payload. So here, first of all, we need to provide what we need this JWT to sign with. So we need to pass in an ID and the ID ID is going to be user dot underscore ID. And then we need to sign, sign in with a key. Now this key will be used to even verify our requests. So later on, when we add middleware, which we are going to do, basically for authorized personal only, we are going to verify that using a secret or a private key, you can see where, so we need to add that. So we can name this password key. With this key, we will be able to author verify that JWT is correct or not. As I said, we are using J JWT to make sure that the user are who they say they are, and they're not hackers. They will let us verify that the contents are not tampered with. And this token will be used everywhere in our application to send requests. And we'll pass that in the header. You'll see that later on, but I'm just giving you a spoiler for what's going to come on later, then say, yeah, we are going have token equal to JWT dot sign.Now we will send this token. So we'll have rest Jason, because with this, we need to make sure that we store the data. First of all, we are going to send this tokens. So this token is going to recite in the app's memory. So we need to make sure that we send it. And also we need to send the user data because we want to store that data in the user provider that we are going to create when we go to the client side, because when we click on the sign in, we are going to return to the big homepage and we want that user data to be accessed anywhere in our application. That's why we are going to send both now how to send both. Well, we can just pass in token and then user, but now the problem comes in token will be accessed using token and then user, but we'll have to specify one more property just to use that user.So instead of doing that, we will have.dot, which is object destructuring. And then you can have user dot underscore dot with this. Basically, if we have a user property, let's say like this, let me quickly add some comments. Say we have, let's say name. So we have name as Revan, then the email as something Ania, Gmail, dotcom, something like this. So basically we are with using this, these three dots, you might have seen it in data as well, when do something for list. So it'll give us specific property. So will this, we have name separately, email separately like this. And then we are also adding token away with this. Basically when we send some data, it'll just give us in a format like this, Right? It will add token to this user part. And now we've used user dot underscore doc, because if user is locked to the terminal, you can just try to log this in the terminal. A big object will come out and that big object is of no use to us. You can just try it if you want, but that user object is of no use to us. So we are using user dot underscore doc, which gives us the correct information that we want having that we can save this much. And let's try to use this API sign and route in a thunder client or the postman, whatever you're using. So let's create a new request pass in this use post and then pass ANP slash slash local host 3000. As I said, you can use local host of Ania and you have sign in. So let's just copy this body, go to the body page, this body and remove name because we don't need name anymore. And then click on send. And here we have it. We are logged in with a specific token that we have received, which is pretty good. I, again, send in, it's going to be the same token. You can see that great. So we have this working now let's bind it to our client side. So now let's just close the terminal, close these files, and quickly go to our service.dot file and create a similar function for signin. So let's create this and I'm not giving you this exercise because this is going to be involving some provider and stuff. So let's do it side by side. So we have sign in user. Then we need to get context, email, and password. Then we need to remove this user because we don't need that anymore. We're not going to send some data. We are going to, well, basically just use email and password. Then instead of passing in the body as this, what we need to do is use Jason, Incode pass in a name and an email. You can use user model, actually my bad. I didn't see that earlier, but it's just two things. I don't find the need to pass in it so we can have email password as password. And yeah, good. Now we need to handle the same error. So now everything here is going to remain exactly the same, but we need to add some changes in on success. If there is some error, we want the same things to happen. And that's why we created this HTTP error handling part. Right? But now we need to do some stuff differently in on success. So you, if we print our body, let's just print it quickly. So we have print res do body and connect to our, the sign in user to our screen. So let's quickly go to our odd screen and have avoid sign in user, then create an empty bracket and just use this person. And then we'll change this to sign in user, remove the name part because we don't need that anymore. And now similar to this On tap, we are going to copy this on tap past it it over a year. And now instead of passing and sign up user, we have sign and user instead of sign up form key vLab sign in form key. And even here, if you've not noticed, we have passed in the form as sign up form key. We need to change that to sign in from key. Please do that. Otherwise, you know, it's going to give us an error. Great. So now we have binded this, let's get our debug console and restart our application And we are going to use test 1, 2, 3. So we have test one, two, three.com and then pass in test 1, 2, 3, click on sign in user with the same email already exists. And this error came in because, well, if you go to our audit service, we have not changed this, right? So let's quickly change that and now let's try it. So we have sign in here. You can see, we are getting our data token, the ID, the email, the password. That means everything is going good. Now we just need to make sure again, let's go to our art service and now in the own success, first of all, we need to save this token to our device so that we can process the state and our application. Now, what is processing state? As you can see, if we just sign in away, you'll see that after we restart our application or after the user quizzes, the application and starts again, we'll again, come back to the screen. The reason being in the main door dot file we've passed in home as odd screen. It is not anything else. Now, how will we do some conditional logic in case you wanted your, uh, home screen? So what condition will we put in now? The condition is basically that we will use this token that will store in our device memory using shared preferences, a plugin, which we will get to in just a minute. And then we will get that data of the user and save it to our database. Pretty simple. Right? So now, first of all, we need to add two plugins, which are shared preferences and user provider. Again, just to mention shared preferences. We will store token in our app memory and with provider, we are going to store the user data because when we log, you can see we get this data. Now we just use this data to save it in our user provider so that it can be accessed throughout our application. And we have state manager and we don't have to manually just pass in everywhere through the construction, our user data. So now let's quickly go to pop.dev. So we have pop.dev using provider. You can see a wrapper around inherited widget to make them easier to use and more reusable. So let's quickly save that, pass it in the dependency. Let's stop a wrap execution as well. And also side by side, let's have shared preferences done as well. And in case, as I told before, if you want any other state management, you can definitely use that as long as you're comfortable to convert them. So let's pause and share preferences, And there's no manual installation required for both of them. So we are good to go, but in case you wanna see the usage and try it on your own, I would highly recommend that, do it on your own. And we're going to use something from your only basically to write the data to our app memory. We can do final press first, get the instance, then use this instance to set the value to our memory. And that's all that we need to read the data, which we will use later on while, you know, persisting the state of our application. We will read the data and we'll read it using something like this. Again, get the instance. And with this instance, we are going to read that using getin here. We have certain it's pretty simple, no need to worry about it. Great. Now all of these things have happened. So here we can have shared preferences, then we'll see it in the variable press. And we are basically just getting their instance. So we have shared preferences dot get instance. And since we are using Ave, we need to use asynchronous. And now we need to basically said the data now, what is our data? Well, this is just token. So we have press dot set string. And then what is the key that we are going to store it with is going to be X Orth Token. Now, if you want, you can store it in a global variable because this exo token, we are going to use whenever we start the application. So we are going to make that functionality so that we can process the state and to get the string. We have to, again, pass in the key name, where we are storing this data, which is exo token, and now we need to pass in a value. And the value is going to be pretty simple, this token, right? So we can use response dot body, but as we know it, we need to encode decode that data. So we'll have Jason decode and let's quickly have that.So we have G Jason decoded pass response dot body, and then use token on this, which is this. And it'll save it in our shared preferences and we can get access to them using this key. And if you go away, you can see this is future as well. So we can just await it. And there's no need to use the bull value that it gives us saying that, you know, this has been a success or it has been a failure, no need to worry about it. After that, we need to use provider and for provider again, we have to create some boiler plate code. So we can have a new folder called providers, which will first have a user provider or dot file. So let's create user under scope provider dot file. And this user provider dot file will be called user provider. Let's quickly create that. Then we have to extend to change notify because we already know that's how provider works. I'm not diving deep into it. You can just check out some tutorials on it. It's pretty simple. Now we are going to create a private variable of user where all of the values are going to be zero or one. So let's have them creator. So we'll have IDs T stringing name as Mt. Stringing email T stringing password, AST string, password AST, add AST type AST token, AST everything emptyAfter that, since it's a private variable, where you going to create a GTA for this. So we have user get user And then return this private variable and create a function so that we can update this user. So we have set user and we have string user, which we will get. And this is string mainly because we are going to pass and response dot body to it. And response dot body is a string. And here we are going to set user, which is this private variable equal to user dot from Jason, which is another function in our user model, which is this. Basically this is calling from map and then decoding the data over there and then passing it to from map. You got the idea and then we'll pass in the source as the string user, after saving that, we just need to notify all the listeners that our user value has been changed. Please rebuild. Now we can go over here and have provider dot of and pass in user provider context. Then we'll set, listen to fault. Since we are outside the build function, every time we're outside, that build function, we are going to set, listen to false. And then we are going to call dot set, user, passing the user, which will be response dot body. And let's take this provider and put it just below the share preferences. It's not anything that would matter, but the thing is, we are getting the instance. Then we are saving that data, and then only we are setting that token And then we just need to navigate to another screen. So here we can have features as the home screen and here let's quickly create a screen. So let's create a folder for that. We'll have screens pass in the home screen and the widgets and all of that will create later on. But for now let's create basically a stateless widget called home screen. Actually right now let's create a state full widget right here itself. So we have home screen passing the scaffold and your, as the body are centered text, which will tell us the token and the user ID E so well, the actually let's print out the whole Jason format or the whole user thing itself. So here we can have final user equal to provider dot of user provider contact context user, which is the getter that we created. Now we can take this user pass in the text, user.to string so that it can be put in the text widget. And now I think most probably it'll just tell us instance of user model. So what we can have is user two, Jason, that should give us the right output. Whereas user two string will just tell us that. Yeah, it's an instance of the user model. And that is like, yeah, we already know about it. Yeah. We are going to use navigator.off context and actually let's remove that. So we have navigator dot push name and remove UN until then we need to pass in the new route name. So let's quickly give this route name and also let's rename this. So we have home screen.dot, and the out name going to be static, constant string, route name equal to slash home. And you have to register this route name in our router dot file. So quickly copy this, paste it down here. And we have home screen, do route name and we have to return home screen. Now we can go there, pass in the route name as home screen, do route name. I'm not explaining any of this code because you already return it multiple times. And it would be a great time waster just to write this again, game right after having that, I think it should work. So let's rerun our application and see if it's working in the very first try. All right. So our application has launched, so let's quickly try to sign in. So we have test 1, 2, 3 other ag mail.com passwords test 1, 2, 3, click on sign in, And here we are getting an error. This happens because you used a bill context that does not include the provider. You added a new provider in your main door file. And that's mainly because in the main door file, we have not registered our provider. So you're basically, we need to wrap this my app widget with a multiprovider widget so that we can use provider anywhere in our application. And then it accepts a child and then also a list of providers because it's multi provider. And then we need to pass and change notify provider and then create, we are going to pass in context and then pass in the user provider. Also let's quickly get that. Yep. Our error now should go away even the warning away. So now quickly restart the app. Now, if I click on sign in I'll pass and test 1, 2, 3, gmail.com pass in the password. Test 1, 2, 3, click on sign in here. You can see, we are navigated to another page and it's showing us ID name, email, password, token, everything. Now, for, as of now, there's no need to know, uh, no way to know that a shared preferences data got stored or not. But now the next step is going to do exactly that. We need to get that string in our main door dot file itself. In this my app widget, we need to convert this to a stateless widget state full widget, and then get that data from shared preferences. And then based on that, we can put a conditional logic over here saying if you want to go to the admin, uh, odd screen, screen, home screen, whatever. So we are going to do exactly that. So now let's quickly change this my app to a stateful widget, because you're going to use in it state aware, and now let's create an instance of the class of final or service or service equal to or service.Now we can take this or service and call function on it, which is getting the user data now before getting the user data, let's close all the other saved files and save this one. So before getting all the user data, let's think what we want to do. So in our art service dot file, we want to create a same request because we want to get the user data to get the user data. We want to get the user data from the API, right? I mean, we have to ask, create our own API to get the data now, before getting the data. We want to get that token now to get the token, we are going to use share preferences, get string methods so that we can get the X or token that we've already stored. Now that exo token can be Nu as well because we logged in. But before logging in and starting our application, we are going to, again, run the, get user data function. Now when that get user data function is run. There's a possibility that token will be null because for, for example, when the user signs, uh, uses the application for the very first time, and we call the get user data function, because no matter what we are running this instate function, right? So whenever we run that in state function, it is going to get that user data. And in that user data, we are using shared preferences dot get string. Now that string that we save in, for example, year, we saved in exo token. But if we are using it for the very first time, that exo token is Nu. So you want to check if that token is null, then we want to show that odd screen itself. Otherwise we want to check if that token is valid or not, because that token can be altered, right? It's in the app memory, it can be altered by hackers or even person who knows about the phones very well. So you want to check if that token is valid or not using JWT. And if that token is valid, then we want to get the user data. So there's a lot of validations. So let's create this, let's use this function just to create another function, to check or to get user data. So let's name that only get user data pass in the bill context, remove required argument, and also let's require remove require because there's only one parameter to pass in. What's the use of the named parameters. Cool, aware before doing any of this, let's comment it out for now. And also let's remove the print statement from your because print is not good in production code. Also remove print from your, and let's avoid the HTTP error handling for now. So your, we want to, first of all, get shared preferences. So we have shared preferences equal to avoid shared preferences dot get instance. After we get that, we will get some token. So let's call the string token, which can be Nu you can see aware because that's what preferences give to us. So you have preferences dot, get string yet string. And then we want to pass in the key that where we have stored. So it'll be X or token if there is no token, it'll return Nu if there is token, it'll give us some data. Now we want to check if that token is Nu. So if that token is Nu you're going to press dot set string and passing the key as X or token and the value as an Mt. String. So with this, we are basically telling that yeah, user has used the application for the very first time, and now it is an Mt. String. Not Nu after that, we want to check if the token is valid for or not. So for that, we are going to create an API. So let's go to our odds file. And we are going to create this in odd GS, because well, it is related to authentication task only. Let's copy this and I would recommend you to not copy again and again, and type it so that you get used to that. Centage right. I'm already used to it. So I'm just copying it again and again. So now the TRICA block is going to stay the same. We have it after that, we want nothing from reg dot body and token will be passed through a header, not through body. So we have slash token is valid as the name. And then we want to remove all the things that we have aware. So here, what do you wanna check? First of all, get the token. So we have token equal to request header, Pass an X or token. Then we check if there is no token that is passed or the token is Nu, then we want to return Jason and you'll see something great away. We'll just return false, no object, nothing with this. It'll just say there's no token because our post is token is valid or not. We just want an answer and true our false. So we are passing in falls away. Then we want to use JWT dot verify. If the token is there, then we want to verify that token. That's exactly what this function is for. Right? So here we want to pass in the token, which you ever received from the header. And then you can see the secret or the public key, which we signed it with. You can see this is the secret or the public key. So we can just use that after that we will check if it is verified or not.So your, we can store it in a variable. So we have constant verified or is verified. You can, uh, take the variable names on your own. So if it is not verified, then again, we have to return dress dot Jason as false. Correct. Now, if the user token is verified, then we want to check if the user is available or not, because I mean, the token can be valid. But what if that token is just a random token that turns out to be correct? So we want to check if that user also exists or not. So we wanna check constant user equal to innovate user dot find, and we always use find one tele, there are many more options. You can just see it in auto search. Find, find one, find by ID, find by ID and delete and all of those functions. But we are going to use find by ID because we don't want to delete anything, right? We just want to get that data now to find by ID. We are not getting ID from request or body, and we are getting ID because we have signed that with the user. So after using verify, we are getting access to that ID property that we are stored in it. You can see JWT, it signs with that ID. So now we are getting that verified object. And on that object, we are using.id property. Now, if that user doesn't exist again, we are going to return race, Jason falls. And finally, if all of these conditions pass in, then we are going to pass in rest. Jason. True, great. So this is our function for token is valid and we've created an API now. So here we are going to have a wait HTTP post again, then we need to pass in the URL. So that will be dot pass, pass in the URL, which will be dollar sign then slash token is valid or not. And we're not testing this API in thunder client, mainly because we will have to get this token and pass through the header. Instead, let's do it right here itself. If there's any error, we are going to see that error only, but in case you want to do it, there's absolutely no problem with that. You should definitely do it. So with this, we are going to get the token rest. So if we put both as rest response, it will be very confusing. So let's name it specifically. And now, as we told, we have to pass in on header. So we have head earth and headers will consist of String, comma string. And as I told before, multiple times, we, whenever we use pass header, we have to pass this content type, make sure to do that because we are using express or Jason. And now along with that, we will pass an X or token. This is the name we're going to give as well as the name of the shared preferences. Key, both are the same thing. And then we need to pass in the token that we got AR and now we have already checked if token is Nu. So we can just pass in that the token is not Nu. Now we are going to get that response. So now we will have our response and then we will just use response dot body. So we have token response body. This is the actual response. So we have Jason decode passing the token response dot body so that we can use some objects on this response, right? So you, this response is going to provide us with true of false, because that's what we have supplied away. True, false, false, false like this. So we are checking if response is equal to true, Then we want to do a wait and get the user data. So yeah, we need to create a API to get the user data, to get the user data. Let's create another API called get user data. So here, what we are going to do is router dot get pass slash, then we'll pass in oath. And this is the middleware that we now need to create. This middleware will keep, make sure that you are authorized. That means you only have the capability to access this route if you are signed in. So now let's create this middleware. So you, you have server and we are going to call this middlewares And your first middleware is going to be S something similar to this. We, we will have another middleware called admin because we want the similar thing to happen with admin also, right? Admin protected routes should be there. And similar to that, we have oath protected route. So here we are going to get JWT equal to require Jason web token. Basically we will pass in the token and we need to verify that token just like we did before. So yeah, we are going to create a function. This is not going to be a route. So you'll have asynchronous request re next, and next is similar to, you know, continue on with the next route because we are going to pass it in as a ware. When we reach, when we use next, I'll explain it to you. Then we have a try and catch block. So we have try catch pass in the error and then pass in re status 500 Jason pass in the error as error message. Then use this tri block to have constant token equal to request dot header. Because every time now, onwards, whenever we use authentication, basically to fetch products, to, you know, save it in card, we are going to use this middleware. So we are gonna pass it in as a header, which is the best thing to do. So we have Xu token, and then we are checking. If there's no token, then we want to return some data. So we have return rest status 4 0 1. And this is 4 0 1 because this stands for unauthorized. So if you go to the website again, you can see we have 4, 0 1 unauthorized. Although the HTTP standard specifies una authorized semantically, this response means unauthenticated. And now we will pass in adjacent saying that the message is no author token access denied. That means that the user has not passed only token what to do now, and now we will have verified. So let's go to our author JS and copy this, paste it over here. And we will verify this token. We are getting from your pass in the password key, and then we want to return rest dot status photo. Oh one again, because it's not on because it is not authorized. And then person Jason, which will be message as token verification failed authorization denied. Great. Now, after this, what do we need to do? This is gonna be a very important step. So make, keep, make sure to keep a note of this. So here we will have request dot user. Now we are adding a new object to this request, which is user, and we are saving something to it, which is equal to verified.id.Now, every time we can't pass in the body, every time we can't pass in the body, the user's ID, right? So now what are we doing is adding this middleware so that here we can perform all the validations, if it's valid or not. And if it is valid, then we are storing user ID in request dot user. So whenever we created create some authenticated route like this one, where we add the middleware, as we can use rec dot user, like we are direct dot header. Now, if I add author, I can add rec dot user, and that will fetch the user's ID to me. Great. Now we can have rec dot token equal to token, and in the same fashion, we can access the token as well, because these are the two things that are given away. And we need to use that later on, somewhere in our application, after that we can call this next callback function.This next, if you don't specify will not go to the next API route. For example, now here we have request response, and this is where to be asynchronous, obviously. So here, basically, if you don't call next, it'll make sure that yeah, it authenticated this, but it won't run this callback function next basically means that it can call the next callback function. So let me quickly add that and thus, we can follow along so we can just check constant user equal to innovate user dot, find by ID. And now the ID we know is rec dot user. If you don't trust me well enough, you can just print this out and see to print. You can always use console.blog. After that, we are just going to send this lab.dot user doco doc. As I mentioned before we UI, we are using doco doc and then pass in the token, which will be request dot token. Now we should be able to get the user data so we can go to the odd service and get the user data. So here we can have eight HTTP dot get pass in the URL, which will be dot par. And the is simply dollar, sorry, like this dollar and pass in with a slash don't forget this slash because URI is nothing with the slash. We've already talked about it pretty much every time and also pass in the parent thesis. After that, we will save this in response. So we will call this response HTTP response. Actually let's call this user response. HTTP response is pretty lame. And then obviously we are using get, but we also need to pass in headers and headers is going to be something similar to this. So we can just copy this and pass it in over here and token, this exclamation mark is not needed because here we have already told that token can never be Nu that's. Our smart flatter is. So now we can take this user provider. So we have variable user provider equal to provider dot of user provider person in the context set, listen to falls, and then say, user provider set user. Now, instead of doing that, you could have obviously used user provider set user. It doesn't matter. Pretty sure I did this because it gave me some errors back then, but it won't give anything to you. Then we can just pass and user rest dot body to set the user appropriately. And that's all that we need. So let's remove this error handling part. Let's restart our application. And actually this is not working because we need to get the, we have to bind this to our UI. So we'll have to run all service dot, get user data cost in the context. And after having that get user data done in the home part, what we can have is provider dot of user provider Context, and let's have that. So we'll have context.user.token.is not empty. So if the token is not empty, that means that we have saved some token. And that means we can go to the bottom bar so we can have constant home screen. And if the token is empty, that means we can go to the odd screen saving this much. We can restart our application. So app has lowered up, but there's one problem where you can see in our server, we are getting this error or router dot get, and O is not defined. So basically in our a yes, we need to go wire and use O but we can't use O because we need to export it. So we can module dot exports equal to this. A, now we can use this a by importing it so quickly, import it and save this much. So wrap started.So let's restart our application and now we are on the home screen directly. And again, if I restart the application, let's go to our diva console. UNC. If I restart the application, we are still on this page. That means a state persistence has also worked. Now we can start working on better things. So now we let's create this bottom navigation bar so that we can navigate better. We navigate between the homepage, the product page, or, you know, the profile page account page, and then finally the card page. Great. No, now let's just create a bottom bar so that we can navigate. So you're in the widgets. I'm going to create bottom bar and you're not creating any specific feature for it because it's a bottom bar and it'll be used everywhere. Basically in that application. After that, we're going to create it as a stateful widget and call it bottom bar. Now this will have a route name because we are going to navigate to this bottom bar whenever we are on the hot, hot screen, and then we need to navigate. So this is the bottom bar that we're going to use. And then we are going to call it a route name and set it equal to let's say, actual home, because earlier it wasn't home. And this is going to be actual home. After that, we can come away and return a scaffold, which will have a body, which we will figure out later on because this body is going to be based on what bottom bar item we are on. And now let's create the bottom navigation bar. So let's remove the body so that we can focus on the UI part. Now, so here we are bottom navigation bar. Then we are gonna pass in the current index. And the current index is going to be end page equal to zero. This will keep track of the current index and we will change this value. Whenever we want to change the current index, then we need to pass and selected item color. So whenever an item is clicked on what should it for should its color be. So we are in to pass in selected navbar color, which is present in our global variables file and whatever we copied earlier, then we need unselected item color, and that will be global variables dot unselected. Navbar. After that, we are going to have a background color, which will be global variables dot background color, and then an I can size, which will be 28. All of this is tried and tested, you know? So in case you're wondering how I got those values. I just put up some random values and got that I can size after that. We are gonna have a bottom navigation bar item and person an I can as a container, not an I can just, but a container because we want a, we want a green line to appear at the top, right? That's why a container. Then we will pass in a width and we will create width at the top. So that in case we want change it any time we can just change it to wire because bottom navigation bar or the containers, width is going to stay the same for every, every bottom navigation bar item. So I'm going to pass in double bottom navigation bar width. So let's say bottom bar width and set it equal to 42. Let's grab this and paste it over here. Then we are going to have decoration so that we can add that decoration, right? So we are going to have a border and border will be from the top. So yeah, border top border side, And we'll pass in the color and this color is going to depend on the page we are on, right? So if this is the zero element, so if we are on the zero element, that means this is a selected item. So if this is a selected item, we want to show the green or the teal color on the top. So what I'm going to check if it's pay, if page is equal to zero, then global variables selected navbar color. Otherwise we can just have the background color so that it mixes in. So we have global variables dot background color. After that let's specify some width. Otherwise it'll be too small. So let's do it at the top again, because this as well is going to be used in every bottom navigation bar item. So we'll call this, let's say bottom bar border with, and we'll set it to five. Then let's take it from here, pass it over here and save this much. And then the container is going to have a child obviously so that we can pass in the I icon. So it'll be just an I icon of home. So we have I icons dot home underscore outlined. Now, copy this much and paste it again. But before pasting it, actually we need to add label. It's actually a required field. So if you don't pass it in, it'll give you an error. So make sure to add it. So we have to pass in over here as well label, which will be an empty spring, and we need one more navigation bar item. So let's put in a third one and quickly let's change their value. So we are in the third one. We have third one. We look after in a while, but the second one will have person outlined outlined. Then if page is equal to one, then we want this and this looks great. Now about the third one, it's going to be the card one, right? So this is for the card. This is for the account or profile, and this is going to be the homepage. So let's save this much and see what we're getting. We're not seeing anything mainly because we have not used bottom bar anywhere. So let's go to the main door dot file and pass in bottom bar instead of the home screen and make sure to use that home screen.dot let's remove that unused import, save this much again, go to the auto service dot file so that whenever we are navigating to the next screen. So yeah, we have it. Yeah. We are going to pass in bottom bar route name and it's not registered, so we need to register it. But before that, I think, yeah, this looks great. So now let's go to our router file and register the bottom bar. So your, we will piece this much, have bottom bar, route name and pass the bottom bar. Okay. Now let's try to restart our application and see what you're getting here. You can see we're getting an error and this error is because we have probably missed label putting labels somewhere. That's what I was telling you. And that's probably in the last one. So let's add it away, saving this much. Let's restart our application and you can see this is showing up. And there's one takeaway that's because we have not changed this. So let's change this for two and here we have it. Sweet. So now we need to work on the cart feature. Now cart icon is going to be a bit different from other one, because we are going to use a package for this. And the package we are going to use is badge so that we can add the number on the top. So if we have a cart here, we can add a number of how many items have already been added. So for that, we are going to use this package.Let's copy this badges. And it's a pretty simple usage. Just add this to your pop spec and we can use that. So I'm just going to use dot, add dependency, pass in badges and stop our app execution. After this pub get is run. I think I can restart our application and then write the code for it. So you're run without debugging. And now in the child, let's wrap this. I icon with a widget known as badge, which will be from the badges package. And now the elevation is going to be set to zero because we don't any other, you know, uh, popping out thing. We just want it to stay along with the, I can, then we are going to have badge content and this content is going to depend on the card. But when we add card, we look into it for now. We will just have a text, a constant text, actually, which will just say a number which will be two for some reason. And then we will have badge color, which will be colors white. Then we have a child and that's all that we need. So let's save this much restart and see what we're getting. You can see two showing up. Also let's change this to shopping cart outline Great. Now, here we have, it looks great. Now the next thing is, whenever we click on any of the icons, we want this thing to navigate away and the correct content to show up. So you, we are, we are, we have to add a packet or we have to add a property for that, which will be on tap. So whenever any item is tapped, what do we need to do? Well, we can create a function right at the top called update page. We will get a page and then we are going to set the state. And the global variable page will be equal to the page from the parameter. Pretty simple. Now we can take this update page pass into over and looks it. Now, whenever I click away, you can see this is shifting great. Now the next thing is to correct to correctly, show the information. So here we are going to basically have a list of widget of pages, which will be equal to multiple widgets that we are going to create for now. We are gonna have a constant centered child text saying what this page is for. Now. We have account page, But above that, we are going to have our homepage and we have already created homepage. So no need to pass in, you know, the centered text, but for card screen and for account screen, we are going to have this so we can pass in account. Let's say card page also great. Now let's take this pages in the body. We are going to pass in this pages because it's a list and we are going access.And the body is going to be the widget at the particular index, which we are continuously changing, which is this page over here. Now save this much. And here you can see, we are getting the home screen, your, the account page, and finally the card page. Now let's design the account page. First of all, then we can design the home screen. So now let's quickly close all of these save files and you, we are going to create a new feature. Let's close the home and odd screen, and you create a new feature called account. This account is again going to ask screens and widgets. We'll create services later on when we need it, but for now we need screens and widgets. So your first thing we're going have is an account screen.dot file. Let's import material dot. Let's create a state full widget. Actually let's try a stateless here. Then we'll call it account screen. We are going to return a scaffold and the app bar is going to be preferred size because here we have, this is the app bar that we need to create. So now we are going to use preferred size for that, and then passing the preferred size that we want. So we want a size that will be from the height 50. After that, we need to have a child which will be an app bar, and we need to pass in a flexible space. The reason for flexible space is that we need to have a linear gradient away, but app bar doesn't have a property to add a linear gradient. So we need to use flexible space using which we can specify a widget, which will have a linear gradient, and that would create that design. So let's quickly look at it. So we have box decoration, passing the gradient as global variables.app bar gradient. Great. So now let's take this account screen, go to the bottom bar dot file and replace this center text with the actual account screen that we have just creator. So now let's look at it. We need to restart it probably. So here we have the app bar showing up. Now let's design this app bar. So in the title, we are going to have a row because we need two things away, right? This is the Amazon logo, the bell I and the SOI. So this is going to be considered as one, and this is going to be considered as another element. So first of all, let's have a container which will have an alignment of alignment or top left. Then we need to have a child and the child is going to be the Amazon logo. Now to get the logo, what you can do is go to the assets folder on my, get a repository, go to images and download all of them because you're going to need all of them. I already have them installed. I'll put it in. So what I'm going to do is in the root of the folder, we are going to create an assets folder. Let's rename this. I don't think I can type it properly, but yeah, we have assets. And then we are going to pass in an images folder and then copy this images, folders, content away after you've installed, you can just take them and paste it over here. Yeah, we have it. Now we need to go to the prospect, do file and add that assets. So we have assets slash images and we are not going to manually specify all the images.So put, uh, slash away here so that it can take in all, everything that is provided over in this folder. After that we can close it, restart our application and pass it in. So here we are going to have image dot asset pass in assets slash images slash Amazon N PNG. That's the name of a file. And here we are getting an error, mainly because we have not passed in children for the row. So we are going to pass in children. And then in the container, we are going to pass in the children. We are gonna pass this container. Now, after that, we are going to have a width of one 20 height of 45. And the color is going to be colors, not black because by default, it'll take it as a white color after saving this much. I think our app fail. That's why we have our own table to see it. Now let's restart the app and see what you're getting. All right. So our app has loaded up. Let me close the file. Full file manager. And you, we have it Amazon end showing up. Sweet. So now we need to create another container, which will have a rope, because as I said, these are two, the two elements are together. So first of all, let's give some PAing. So we have constant insert dot only from the left. We are gonna have 15 from the right. We are gonna have 15. Great. Now we are gonna have a child which will be a row. And in that row, we're going have children, which will all be constant because it is just Ikes that we're going to display, uh, bell Ike and search Ike. So yeah, we are going pass in padding, pass in the padding as sets dot only from the right side 15. And then we want a child of Ike and the ICAN will be Ikes dot notification outline. And let's save this much. You can see, we are getting this I icon great. Now we can copy this. I can and paste it 10 again. So we have Ikes dot search After saving this much. You can see this showing up again. Now all of them are together. So basically what we've done is this is one element. This is another element. Now we have put them both of them in a row. So now to make them go apart, what we can do is in the parent row, the first, most row we can pass in a property of space evenly. So here, what we can do is go at the top and have main access alignment as main access, alignment.space, evenly, and actually not space evenly, but space between, and here you can see it's showing up. Great. Now we have the app. Now the next thing is to work on this part, which is saying the hello plus the name of the user. So for that, we are going to, first of all, minimize this app bar. Then we are going to pass in a body because this is a scaffold and the body will consist of a column, which will be a column of constant widgets, because everything that you're going to pass in your is going to be in the widgets folder so that it doesn't get crowded away. And there's no unnecessary rebuilds as well. So here we're going to have underscore app bar under got that. This is the name of a file. I couldn't think of anything else. So you are importing material, data, creating a stateless widget, calling it below app bar, and then returning a container which will have a decoration of constant box decoration. So we're gonna have a gradient which will be global variables dot a bar gradient. After that, we are going have a padding of constant insert dot only from the left. We are going to have 10 from the right. We are going to have 10. And from bottom, we are going have 10 and let's just name it properly. So we have child passing the row and we have a row mainly because, well, it's hello, admin. Now we are going to have a rich text. And rich text is mainly because, so that we can have two, you know, text in one line, you could use a role for that. But I think that rich text is also a great option for that. So yeah, we are gonna have a text span where we are going to have a text saying, hello, and we are going to leave a space where, so that, you know, there's a space where like this. So yeah, we are gonna have a style of constant textile Passing the phone size as 22 and color as colors, draw black. After this much, I think we can have children. And this children is again gonna consist of all the text spans so we can just copy this text van, please it away. And we need to pass in the user's name and we have access to user's name using a provider. So why not user? So we have final user equal to provider dot of user provider context user. Now take this user pass in over here. So we have user.name And yep. We have it. So let's pass in a parent thesis that we've missed and pass in the below app bar over here. Let's see how it's looking here. You can see hello, Revan showing up. So now, if there is something like this, just to resolve this error, what we can do is go to the app bar, pass it, pass in a row over here. So we have wrap it with a row and let's save this much and you can see it extends further three. Otherwise you could have just used container and given in the Medoc query dot context dot size dot width. And that should have worked as well. After that. The next thing we want to wear is these buttons. So let's pass in a size box of height 10 and we've passed in cons convey. So there's no need of passing in cons again and again. So yeah, there is some spacing as well. Now we want to create this layout. So first of all, let's create a widget known as topButtons.dot Let's, import material dot. And then we want a state full widget and we are gonna call it top buttons. And then we are gonna return a column because you can see they're all in a column. And in that column, we are going to have row two row just to demonstrate it to you. We have a column, this is a column. And in that column we have a row. And then again, we have another row pretty simple. So let's quickly create that. So we have return a column and children, so let's pass it a row which will be children and will consist of these buttons. Now you can see these buttons are being excessively used in this place. So we can create a separate widget for that, which will be reusable. So we have account button do file let's import material dot, call it a stateless widget, and then call it account button. And then over your, we are going to return a container with margin of constant engine sets dot only left 10 symmetric, sorry. And from horizontal, we're going to have 10. That, that means from the left hand, from the right, we are gonna have 10 and we have height 40. Then decoration will be box decoration Where the border is border dot. All color will be color stored white, and there is no width at all. That means there is no border at all. Let's go where you can see Now we need the border radius. So we have border radius of border radius dot circular 50. Now, in case you're wondering that we can see some border away, but away we are setting the border with a zero. You'll realize later on when we use, uh, the button, because the button we're going to use is outlined button so that it can give us a nice clean outline. We are just setting the border radius away. And if we set the border radius, there is going to be an automatic border applied, which we are removing aware. And then we want a color of colors dot white. After that we are gonna have a child which will be an outlined button. So the child aware is going to be a text and the text will be whatever we get from the constructor. So let's have final string text and require this from the constructor. Then pass it in over a, your then the style is going to be a constant textile where the color is going to be colors.black and font. Weight is going to be font, weight dot normal. Now this is an outline button. So we need an on tap also. So whenever we click on that, what should happen? So we want that from the structor as well. Let's call this on press. So let's create it from the construction as well. So we have final void call back on Tap, required it from the constructor. So we have on tap and here are in the on press person, the on tab. Great. Now let's use this account button and see how we need to style this account button moving forward. So the very first button that we have is your orders. So yeah, your orders. And when we click on it, nothing is going to happen. As of now, also we need to pass in top buttons away just to see any input or output. Sorry, here we see it. Your orders looks great. Now let's add a bit of, you know, curve to it. So in the account button, we are going to have a style which will be elevated button, not style from so it'll capture elevated button style. And the primary color that it's going to have is colors.black, 12 dot with opacity 0.03. This is just a tested value.But in case you don't add opacity, it'll look very good, very bad. And this is this color that we can see. And we add a border radius, obviously. So let's copy this line, paste it over here. And before that, we need to specify the shape in which we can specify the border radius. So we have rounded, rectangular border, and there we can specify the border radius. So we have border radius. <inaudible> over here, suite. Now, V this looks great. Now let's just increase it size. So to increase it size, what we can do is wrap this container with an expanded widget so that it can take all the available space. You can see it takes everything. Now, if we add another account button, it'll diminish its size. So we can have another button that says, let's see what we have tell seller. So we can pass in turn seller. You can see they all, they both taken the maximum space. They can get after creating this row, we need to create another row for logout and your wishlist. So we can just, you know, copy this row, paste it down your, and before pasting it, we need to paste it out. So we have constant sized box of height. Then now we have log out. So we will pass in, log out, and then we need to pass in a text. That will be your wish list. Sweet. So yeah, we have, it looks awesome. Now, one thing that I noticed in this app bar, the below app bar part, we are not bolded this, so what we need to do is go to the below app bar dot file and your in the user.name, we have all this and extra thing that we need font way bold. And if we save this much, it becomes too bolded. We don't want that. So let's pass in w 600. All right, this looks great. So after restarting this and creating these buttons, the next thing we need is, again, a sized box after which we can have the list of orders. So what I'm going to do is space it out even more. You can see there's a lot more space there. And now we are going to create a new widget called orders. So that will be orders dot, dot. Yeah, we are gonna import material. Let's quickly import that. Then we need to create a stateful visit because we are going to Fe the orders that the user has made. And we are going create an API for that for, so we know that in future, it's going be a stateful visit so we can just create it right now. So now we have column, and then in the column, we need to return children. Now, the very first child that it's going to have is going to be well, this part, which is this part, which is a column, and then we need a list view builder so that we can build all of these products. So these are the two things that we need. So let's quickly work on them. So we have row passing the children. And the very first child is a container saying, actually we need some padding. So we have constant sets dot only from the left. We need a padding of 15. Then we need a child which will be of the constant text saying your orders. Then we need a style of textile and the textile will be font size as 18 Color as colors black. And I don't think we need to mention that. So here we have the color and we'll pass in colors black. And I don't think we need that. So let's just remove that and see if we need that or not later on. So we'll pass in the font, wave, wait as font, weight dot w 600. And with this much, let's take the orders and put it in the account screen. So we have orders go to this and you can see your orders showing up suite. Now we need, let's put trailing coms. Now we need to pass in another container. So let's copy this container, paste it again. And we have C all. And one other thing is that we don't need it from the left anymore. We need it from the right, because it's a, it's in the top, right? So yeah, we're going to have a color and the color is going to be global variables dot let's import it. So we have global variables dot selected navbar color. Let's remove this constant from your, and yeah, let's go VRC. Let's put this as a small, and now let's space between these two row elements. So we have main access alignment as main access, alignment, or space between your, we can see it looks great. After that, we need a list view builder to display our a product. So let's create a common display products or order, sorry. So here we are gonna have a fixed size of container. And it's very important to mention this height. If you don't mention this height, it's going to give you a render box flow error. You can pass in, you know, expanded widget, but it'll take in all available space and it won't look good. Also, we need to create this outside of the row. So let's copy this, paste it outside the row in the column or trailing commas. So you, you can see they're all in line now. So now very first thing is padding. So we have constant agent sets dot only from the left. We have 10 from the top, we have 20 and from the right zero, because it's going to be very scrollable. After that, we have a child with list view builder. And for now we are going to pass in constant index And create it like this.And yeah, we are going to return under return the product that we're going to create. But before doing that, but earlier we need to pass in an item count, which will be three, let's say, and year to return, or to view something just for design. We have to create a manual list. So, you know, just a temporary list that we are creating. So here, what we can have is list, which will be called list. Let's say it's which temporary, so we can name it, anything. So here, what we need to pass in is, well, first of all, the image, so we have image and the image is going to be anything that you can find out what I'm going to pass in as the image is from unsplash.com. So you can just go over there and search one thing. So I'm just going to take this copy image address based it in over after that, we are going to have the products, actually, that's all that we need. So let's remove it for our, for our application for now. You know, we are just going to have images because here, if you see, we are just display the images of the product. So let's copy this paste, it paste it, paste it. Let's say four times, we can take this list, Pass it in a way. So we have list dotting, and then we are going to return a product now to return a product. What we are going to return is a widget. So let's create a single product.do. And this is going to be a very, very useful widget. It's going to be reusable everywhere in our application. So we're going have import material dot a stateless widget, and it's going to be called single product. This will be used even in the admin side, even in, you know, everything basically. So we have to pass in a padding, which will be cons edge, insert dot symmetric, and from horizontal direction five, then we need a child as a decorated box so that we can just create, you know, A decoration. We don't need a container for that. So we can just pass in decoration as box decoration. So we can have border as border dot, all pass in the color as colors.black valves and width as 1.5. If you come back, if you come back away, you can see that the border over here is like this. So we need colors.black dwells and colors. Black dwell is going be a very useful color for us because it's going to add act as a separator everywhere. Now, after that, we are going to have a border radius, which will be border radius dot circular five, and then the color will be colors dot white. Then we need a child which will be a container. And then the width will be 180. Padding will be constant sets dot all 10. You can see there's, PAing everywhere over here so that it looks neater and cleaner. And then the child is going to be an image.network. And then we need to pass in the image. Now we'll get the image from the constructor. So we have final string image. Now we can click on this. Well, I can generate a construction, Then pass in the image over here. And the fit is going to be box fit, Dot height, fit height. So it'll fit according to the maximum height that the image can take. It doesn't care about rest of the things then we can have with as 180 passed in, it are taken the same with as the entire container. Now we can go there and return a single product. Now it requires an image. The image will be list at index and that's all right, because it is a list of string. If you go back there, you can see it's a list of string. That's all that we need to do later on. Then when we create our own API and, you know, create some stuff, then you will realize how different this will get. So here we have it, your orders. So now, instead of having this as a vertical thing, what we can have is scroll direction as access dot horizontal. Because right now you can see it's vertical. That's why rest of the things are not even visible because it's vertical. So, and the height is one 70. Now, if we save this much, you can see it is visible to us now. And it looks pretty good. So our design for this screen is also completed.Now, the next thing we want to want to work on is the homepage UI. So let's create that quickly. So now let's close the terminal and all the saved files. Now, what do we need to do? Well, close this account page. Let's go to the home screen, do dot again and create a widgets folder now because we wanna create widgets. And it's that UI that we're creating. Now, let's quickly look what we want. This is the thing that we are going to create. So first of all, we need an app bar. So let's quickly create that, right? So now in the scaffold, we are going to have an app bar again, the preferred size. So what I'm going to do is go into the accounts screen now to the account screen, not account button, sorry. We are gonna go in the account screen, copy this app bar widget.And then again, close this much, come over and put in the app bar. Now, obviously we need to make some changes over, but before that let's import app bar Gradon. Now the title is going to completely defer. We can see in the title, we have this a bar and the mic Ike. So now what I want to do is instead of returning this container, what I'm going to do is wrap it with an expanded widget and remove this alignment. We don't need that instead. We will give it a height of 42, then a margin. That's why we are using a container. Otherwise we would've used a sized box. And then we have only from the left, we wanna give 15, you can see in the picture, let me quickly go there. There's some margin aware. That's what we are doing after that in the child, we want to wrap it with a widget that is called material. We don't have any image over. So you gonna have a material. And this materials purpose is just to give some elevation and some water radius. So we have water radius dot circulars is circular seven. We could have wrapped with container and give it it, given it a border radius over. But since we want some elevations, because you can see this pops out and thus the elevation is going to be one. And then we want a child because we are going to have a text form field past. Now we could have used the custom text field, but you can see that the design defers. So we are gonna create the text form field manually away. Then we need a decoration. The decoration will be input decoration. Then the prefix icon is going to be an inkwell widget because when we click on it, you know, it gives us kind of a splash effect.That's why, so we're gonna have an on tap property past over a year. Then we need a child which will be a constant padding. Then the padding is going to be and sets dot only. And from the left, we want six let's quickly go there. So we have a left task six and then the child away is going to be an, I can saying I cans dot search. The color will be colors.black, and the size is going to be 23. Great. Now let's go there. You can see our funny text form field showing up, but there's more of an error because we have this container. So let's remove that. And here we have it. Now let's design this to look something like this. So the very first thing that we do is in the text form fields input, decoration itself over here, I guess. So we have filled past in as true. The fill color is colors dot white. The content padding is cons agency's dot only. And from the top, we want 10. After that, we are going to have a border and the border is going to be constant outline input border. And then we want to give this again, a border radius of circular seven. So let's just copy this, paste it in away. And actually I made a mistake. We want to pass in border radius dot all, and then the radius dot circular seven. Now we can remove this much. Then we need border side as border side dot none. Let's see this much. Then we need an enabled border. So let's pass in an enabled border and this will be similar to this border. So I will just, you know, copy all of this and pass it. Actually, we need to copy this, pass it in. And the border radius is going to be border side of color, colors.black 38. And the width is going to be one. Now, since this is constant, it is giving us an error. So let's remove this pass in the constant array and passing in colors, draw black 38And passing in constant again because we made an error. Cool. So if you come aware, this looks something like this. If you click on this, you can see there's some effect due to which it becomes flat. Otherwise it's elevated. Let's restart this. You can see again, there's some border, but if you click on this, it comes back to normal. That's exactly what we want. Now. Finally, we want to pass in a hint text. So let's pass in the hint and we need to pass it in the input decoration. And here we are going to pass in search Amazon dot end, save this much. Now this doesn't matching with this. So we need to pass in the textile. So we have hint style pass in the constant textile. And then the font weight is font, weight dot w 500 pass in the font size as 17. And that's all that we need. So let's save this much. Yeah, we have it. When we look at it, it looks great. Now we just need a mic icon. So we can quickly create that since we are in a row. So what we can do is over here, have a container saying color as colors dot transparent, then we need a high 42 then margin of constant sets, dot inserts dot symmetric in the horizontal direction we need 10 And the child is going to have a mic, right? So we have constant ICAN as I icons dot mic color as colors.black, and the size is going to be 25. If we go back away. Now this is matching with this. Let's restart the application. You can see it is matching, but still it's not clearly matching. And the reason is because you can see there is some spacing over which your, sorry, there's some spacing over here, but there's no spacing over here. That means our a bar size is a small bit smaller. So we can just change this to 60. Now, this looks super good. I am pretty satisfied with it. So now we can work on this address box part. So now what are we going to do? Well, first of all, just minimize the sad bar. It takes in a lot of space and in the body, we are going to have a column which will have children. And then the first child that we have is an address box. So let's create that address box in a separate widget. So we have import material dot, a stateless widget of address Box. So yeah, we are going to have a container of height 40 then decoration. And this is not going to have the same linear gradient as this. You can see it away. We have this linear gradient, but this linear gradient differs from this. So we're going to manually create it. So we have constant box decoration and the gradient is linear gradient pass in the colors. So the colors are colored or from AGB, which stand for alpha red, green, blue. And then we can pass in 2 55, 1 4 to 2, 2, 6, and 2, 2, 1. Then we can copy this past it away. And your a is again 2 55, but R is 1 62. This is 2 26. So let's change it to 2 36. And this will be 2 33. Let's take this address box, paste it in over a year and save it. Let's put some trailing comma so that we can format the document. You can see it's giving us a color similar to this pretty cool<affirmative>. Now we need some stops. So we have stops as 0.5 to 1.0. Yep. Again, looks pretty cool. And after that, obviously we need a draw so that we can include this icon, then this text. And then again, the second, so let's go there, have a child as raw. Then the children also, you, we are going have a padding of constant sets dot only from the left. We are have 10. So the row is going to be a constant. I icon as Ikes dot location underscore on underscore outline. Then we have a high size of 20, and also let's put a comma way here. Let's put some comma so that we can form other document. And here you can see, we have the I icon showing up with some pattern. Now we need to create a text. Now the problem with this text is, first of all, it can overflow. You can see whenever it overflows, meaning the address is too long because usually the address is going to be too long. So, so in that case, what we are doing is making sure there's dot and that is done using a property known as text overflow dot SIS, but we also need to make sure that we get as much space as we require for this. So we'll have to wrap it with a expanded widget and then only we can use SIS so that it gives us this dot format. So let's do it. So we have expanded, The child will be padding and the padding will be constant edge, insert dot only from left five. Then the child will be a text and we are not in the children again of the row. So let's go over there, pass in the trailing com. And here we have the text. Now the text is going to be well delivery to the name of the user, uh, hyphen, then the address of the user. So let's quickly write it. So we have delivery to, and we use string interpolation, user.name, and let's use user's name. So we have final user equal to provider Dot of user provider, context dot user. This is nothing new. That's why I'm going quickly aware. Then we can pass in the, uh, dash and then we can pass in user address. And users wrote address can never be Nu because we are passing it as an empty string. And even if it is Nu, at some point, we have some, uh, work done so that it always shows us an empty string. So here, if you go, you can see there's nothing showing up and you won't be able to see the magic of this expanded widget and then the texture overflow. But you, you need to trust me on this. When we just pass in the address, you will be able to see. So now constant textile will be font, weight, font, weight dot w 500 pass in the overflow. And overflow is text overflow. SIS SIS stands for those dots. Fade star is when you know, the starts, the text just fades away, but we want SIS because that's a better user experience. In my opinion, after this expander wet, finally, you will see this dropdown icon so we can create that. So we have constant padding and the padding is going to beset dot only from the left. We have five from the top. We have two, let's see this much. And in the child, we have ICAN as I icons dot arrow drop down outlined, then the size will be 18 and yep, we have it. You can see it's looking pretty cool. Now, since this is expanded, you can see the I icon is mentioned earlier when the address comes in, this will look less awful. And the way the address is going to work is we are not going to ask for the, ask the user for any address in the starting itself. What we are going to do is whenever the user clicks on this ad to card goes to the order page. And then for the first time, when he enters their, uh, you know, the address we are going to save it in our database. And then we are going to keep track of that address always. That's how it's going to work. So now having the address box in place, let's create this category list. So let's close this and here we are gonna have a constant sized box. Let's create that quickly of height 10, then let's remove this. So I do command first stop. And what I'm going to do is, so now let's just remove this constant from your, pass it in the column and yeah, we have it. Cool. Let's also remove this user because we don't need the provider. So of course we'll have to remove all of this stuff again. Sweet. So now the next thing is the categories thing. So what I'm going to have is pretty simple. Again, we are going to create top underscore categories, your dot file, import material dot, create a stateful widget for them. Let's create a stateless widget for now. So we have top categories and we are going to have a container of height 60. Then the color is going to be colors dot white. Obviously you can see the color is white. And even if we don't mention, it's not a deal, so let's try to not include it. And the child is going to be a ListView builder because we have five things away. So let's build it out using ListView builder. So we have list review builder. Then we have, uh, context and then index pass.Then we have an item count, And now we need the items for this, the items for this, we have already installed the images. So we have the appliances books. These are all category images. So we are going to use them, but just to initialize them in a list so that, you know, it stays good enough, very editable. So we are going to add them in the global variables. So if you want to get access to them, you can just go to this repository and copy all of these things and put it in the global variables class. So here we can go there. So here I am in the global variables class, I can just pace them over here. You can see now, save it, go by your, and access them using global variables dot carousal images, length, and it's not carousal images, sorry, it's category images link. Then we can get access to return a column because well, it is going to be column, right? You can see where a column of this image and this mobile text. So we are gonna have children as the container and the padding going to be constant sets only from actually let's do symmetry. So we have horizontal as 10. Then we have child, and then we are going to use clip RX for this so that it appears as, you know, a circular thing, or you can use, uh, circle avatar widget for this. So I'm going use clip R And then we will specify the border radius, which will be border radius dot, circular 50. Then the child is going to be of mage dot asset, and it'll be global variables dot category images at index at image. So if you just go in the global variables class, you can see it is a list of map of string com mastering. So here we have title, then mobile's image as this image. So we are accessing suppose the zero element, then their image property. That's exactly what we're doing over here. And since this can be nullable, we can put an exclamation mark. Now we need to specify their height. So it can be first of all, box fit dot cover. Then we can pass in the height as 40 the width as 40. And that's all. So let's save this much and see what we are getting. We're not seeing anything mainly because we are not used top categories. So let's go our pass in the top categor, we are passing the top categories, and now we are able to see this. Now you can see, this is pretty funny. We just need to use them horizontally. So what we can do is scroll direction as access dot horizontal. Now it looks great. Also let's give some padding to each and everyone. So let's give up a specific extent to which an item can be there. So what I'm going to do is pass an item extend, and you're passing 75. Every item is going to have a width or the extent as 75 just looks neat. Also, let's remove this container to say size box. Now, after this container, we need a text that will say the category that we are having. So you are, it's going to be something similar to this, paste it in wire, and it'll be title. If you go to the global variables, you can see this is called title. That's why now we have style as constant textile, and we need to diminish the font size, which will be 12 because it's lower than the usual. And then we can have a font, weight of font, weight dot w 400. Again, save this and you can see this is coming out. Pretty cool. That way, exactly the way we want it to come out. Looks great. Now the next thing is this carousal image. And now if you haven't noticed it already, this is carousal. So meaning if we swipe on it, it'll show us other images. So for that, we are going to use a plugin called carousal image. So here we have carousal slide already. So this is a plugin that we're going to use. So let's install it. I'm going to use dependency and stop a app execution and close the top categories because we are done over even the global variables file. We don't need to add anything else. And now you create a new widget for carousal or carousal image do that.So yeah, we are gonna import material do, uh, let's import it, material dot, then call it a stateless widget, call it carousal image, return, carousal slider. This is what comes from the package. Carousel slider dot let's also get our app running after we've specified the items parameter and the options parameter. What is this option going to be carousal options. So let's quickly add them. And now we can get our app running. In the meantime. Now we can focus on how it's going to look like. Well, first of all, the items is going to return a list of widgets. You can see that now art items are going to be in a separate list that we have in global variables. We have already added that. So if you go to the global variables, you can see, we have carousal images over. We're going to use each one of them. So what we need to do is map over every image in the list, and then we need to return an image based on that URL. So what I'm going to do is global variables dot carousal images dot map. We will get I, so we have I, and then obviously we need to convert it back to a list. So earlier what we need to return with IE is a builder widget. Then it'll accept a builder parameter. And in that builder parameter it'll return to us build a context. So here we are going to return image.network, passing the image.network, which is I E when we map away, we get that URL. And then we are using fit as box fit dot cover, and the height as 200. Cool. This looks good enough. Now we need to pass in the carousal options. But before that, let's see how it's looking. So here we can again, have a size box of height 10, and then finally we will have carousal image save this much. And here we have it. At least it's now a working carousal, but now we need to make sure it takes in all the available width so that what we can do is go to the carousal image In the carousal options, we will pass in view, port fraction as one, and the height as 200, you can see it is failure, a specific height, so that all images have the particular height in case you want to change it. The height does not differ and does not look ugly. So here now this looks like a proper carousal, and it's pretty neat. Finally, we need the deal of the day and this deal of the day is going to work on the rating system. So after we integrate the rating system in our application, we'll be able to show the proper deal of the day product. But for now, we are going to keep it as a static image and a static text. So what I'm going to do is in the widgets have deal of the day, do we are going to import material dot, create a stateful widget. As I said, we are going to create an API for this. So we have deal of the day. Then we are going to have to return a column and it'll be wrapped by a gesture detector. Because when we click on this, we need to get to the new page to display the details of the product. But now we are going to have children, the container, which just says that, yeah, this is the deal of the day. You can see that and it's in the top left. So we are going to have alignment as alignment.top left padding as constant insert dot only from the left 10 from the top 15, after that, a child with constant text saying deal of the day. And then we need a style of textile with font size 20, say this this much, we are not seeing anything because we have not bound this to, uh, UI. So let's quickly do that. So just after this, we can have not a constant because you already have a list of constraint. So here we just need to type and deal of day. And now we can see deal of the day correctly showing up pretty neat. Now we finally need to show an image.network, which will for now just show a static image. So again, we can go to unsplash.com and get a new image. So I'm just going to copy this image address and paste it in over here. Now we need to specify certain height. You can see, but before that, we can go to the home screen and write this column with a widget known as single child scroll view. So that in case there's any render flow error, you can know it's scrollable. Always. You can see that now in the deal of the day, we need to specify certain height. So the first of all, we are gonna have a height of 2 35, And then we need to make sure that the fit is box fit, dot fit, height. This looks great. So in this particular height, it's going to fit now for now, it's looking very bad, but when we add our own products, it's going to look neat because it's going to be, uh, PNG format image, And it'll contain the entire products height. We don't want them to go according to their width. We don't want them to take the entire width. All we want to show is the correct height of the product and the correctness that it shows. So after that, we finally need to add all of this price and name of the product, all of that stuff. So yeah, what we can do is have a container with padding of constant sets dot only from left 15, from top five from right 40. And this will be the product name. That's exactly what we want. So you're in the child. We are going to have text as the product name for now. We can give a star name. So let's say everyone is on sale. So we can have max lines as two and text overflow. So let's have overflow as text overflow dot Ellis, again, the dot format that I've already told to you. And for now, let's just give it a constant text because later on, it's always going to change. So we'll have to remove this constant and let's see how it's looking. It's not looking great. So yeah, what we can do is make some corrections, have a padding, uh, sorry, just have an alignment past in which will be alignment.top left here. We have it. Now looks good. As the name gets bigger, you'll understand why we are using such a small form size, but before that we needed to create product, right? I mean the price of the product. So now let's just add that. So we have container Pass in the padding. So let's copy this padding, paste it in away. And it'll be only from the left 15 pass in the alignment as alignment.top left. And then we need to pass in the child as a text, which will be slash dollar because we want to display dollar, right? I mean it's nine $99. So you want to display dollar. And if you use dollar, it'll consider it as string interpolation. So we have to PA pass in back slash dollar, and then we have dollar as the price. But for now we are not depending on the price from the API. So we can just pass in hundred like this, and also pass in constant aware. Now, if we see aware, this looks good, but it's very small. So we can just increase its font size. So we have style as a constant textile and pass in font size as 18. Let's remove this one now and there we go. Dollar a hundred looks good. And final thing that you'll not be able to notice as of now is we want to display a list view builder below this so that we can show other images of the same product. So to do that, we are going to go below, add a row of images. So let's quickly add that. And it'll be main access alignment as main access alignment.space between then the children will be the product images. So for now we can just create image.network pass in the images. So let's quickly grab some of the images from Europe and let's paste it more times, let's say four times more. And then we want each of them to have a fixed width, height and all of that. So let's pass it in. So we'll have fit as box fit, dot fit width.So it, so here it's going to fit according to their width so that, you know, it stays in a proper constraint and the width can be hundred and the height can be hundred as well. So that we create a box, right? I mean a square. That would be good. Now, if we save this much, you can see we got a render flow error, and that is expected because we need to wrap this row with again, a single child scroll view with the help of the single child scroll view, we'll be able to pass and scroll direction, which will be access dot horizontal. Now we save this much. You can see it's scroll label and it looks good enough. And finally, below this, we just need to tell that, yeah, let's see all the deals of the day. So we have container with padding as constant edge and edge dot only. And from the left 15 from the top 15 from the bottom 15, and in case you don't want to write all of them 15, what you could have done is pass in symmetric away and then vertical as sorry, Ania vertical as 15, because top and bottom is 15. And then you could have removed this left to say, copy with left 15. This is also great. And the earlier one is also great. Both of them look great. <laugh> So we have alignment.top left, and then the child will be text saying, see all deals. Now we just need to pass in the style, which will be a textile. Now the color for this is going to be colors, dots, and the shade will be 800. All of this is tried and tested. If you want, you can just use different shades and see which one you like. I'm preferring this one. So now if we scroll here, we have see all the deals and it looks magnificent. That's the way I want it. So our home screen UI is also completed and it looks exactly the way it, we, it to look now in case you're wondering why deal of the day looks shabby, not like this. When we add great images, you'll understand why it looks great enough on this. Now, the next thing we want to work on is the admin screen, so that we can add products and use real products so that whenever we click on this mobiles, we can see the proper categories. When we click on this essential, we can click on, uh, proper categories. We're not going to design card because we design card only when we are able to add them to our card for now, we just need to be able to add products. And for that, we are going to go to the admin side inside.And for that, we'll always have to do some conditional rendering logic. So you are again in the main door dot file. We'll have to check where if the token is not empty, then we need to check. If the user's type is not, Is a user. If it's user, then we want to show that otherwise the admin screen. So let's quickly do that logic and then work on the adding products feature. So it's pretty easy for us. Well, we can just copy this past it away and have user dot type. And now we wanna check if it is equal to user, right? So if that type is now equal to user, then we want to show the bottom bar, otherwise the admin screen. So for admin screen, let's create a new feature. Let's close all of them and now create admin feature. This will have screens. And now the screen over here is going to be admin underscore, screen.dot. Here we are gonna import the material dot, create a stateless or state full widget. And this admin screen is going to work in the same way as a bottom bar, because it is going to consist of bottom bar, displaying several things like this. Here we have the home button, the analytics button, and the orders button is gonna be pretty similar to the bottom bar. So after having that, let's turn it this into a scaffold and let's keep it this way for now. Then we can go to the main door dot file and you put a call in and then pass the Ironman screen. Sweet. So now if I restart the application, I should see a blank screen and we are not seeing the blank screen mainly because we have not changed the type of in the MongoDB. So let's click on this edit icon using which you can edit your type of the user or any other field. And then we are going to change this to admin and then click on update. After doing that, we can just click on restart and here we have it, a blank screen. Now in case this is, uh, irritating you, the debug banner. What you can do is go, we are in the main dot main dot file. And here we can have B box show, check mode, banner, and set it to false. And now this is gone. Great. So now we can close rest of the files and go to the admin screen here. The very first thing is, again, the app bar that you want create, you can see this part idea and to create this kind of a bar. We can just copy it from somewhere. So we can just go to the account screen, copy this, a bar that we are minimized. Let's quickly copy all of this. And again, minimize this go in the admin screen, pass in the app bar, this app bar click on save. Obviously we need to import global variables. And then again, click on save. You can see Amazon dot, showing up. Now we need to remove this bell and this kind of icon. So let's remove this whole container and pass in constant text admin with a textile, which will be basically that. Yeah, we want to bold this out. So we have font, weight, font, weight. If you go, you can see, as I told previously, this is all the white color. I just wanted to demonstrate this to you. So now we can change the color and set it to colors, draw black. And yeah, this looks great. Just similar to this. Now, what we need to do is create the bottom navigation bar. And again, it's gonna be pretty similar.So let's copy the contents from a bottom bar dot file here and just going to select well, everything. So let's select everything and paste it in the admin screen. So bottom I'll minimize the app bar and here have the bottom nav bar here. We have it. Now we need to create these variables so we can create them or actually copy them from your itself. Yeah, we have everything. So now we can just paste it. Now we need to create some different pages or widgets because we want to render different pages. So your I'm we just going to copy the center widget until we make those widgets. So we are going have analytics page, and this is going to be the post page. We are going to create post page just right now, but for some time, let's just keep it so that we don't have to deal with some errors. And now we don't want badge in our application. So we are going to remove this bottom nav bar item and copy this bottom nav bar item, paste it down here, and this is going to be the orders. And we are going to check if this is two. So if this is two, we want this, we've done this logic. We've covered this logic. So we need two to worry, and this will be all inbox outline here. We will have analytics underscore outline because this is analytics and this is posts. So we will have home underscore outlined only here. We can see the correct symbol showing up and it's okay. Now let's create a post page. So we will have in the screens itself, we will create posts, underscore screened, or that other thing that you could have done is made a views folder and created views in that.But I'm not doing that after that, it's going to be a stateful widget because in just a while, after creating the UI, we are going to create the products and display them. We are going to create APIs for them that side. So now we have scaffold your, we are going to return a body and the body for now can be a centered child text saying products, and we can put cons for them. But instead of doing that, we are just going to pass in cons for center, because now we are going to have a floating action button. This floating action button you can see is over here. So this floating action button is going to help us go to a new page where we can add products. And instead of post screen, they should, they should be product screen. I'm not sure why I named it that way, but now let it be. So here, I'm gonna have a floating action button with child as a constant I icon of I icons.ad, and then on press is going to be a function like this. And then I'll just save this much and you can't see anything because I'm not bound this post screen to the pages widget that we list of widgets that we have. And now we can pass in cons to a yeah. Cool. Now we can go away, restart our application. There's absolutely no need, but yeah, we have it floating action button. Now we want this floating action button to appear in the center. So what we can do is floating action button location as floating action button, location.center float, and yep. It appears in the center.Great. Also, another thing that we want to add is a tool tip. Some people won't understand what this is. So if the long tab they want to see what is happening. So tool tip will help us with exactly that. And we can say, add a product. And now if I long click on this, you can see, add a product shows up. Great. Now let let's create, add post screen or add product screen right now. So let's name it. Add product screen.dot. We will import material dot, create a stateful widget and call it, add product screen. You already know why this is a stateful widget, because you're gonna create APIs. And along with that, we are going to have text form filled because we are going to create a form. So here we have the UI of this. So now again, we will return a scaffold layer with a body and an app bar. So for app bar, we can copy what was there in the Ironman screen. So let's quickly copy all of that and paste it away. Now we just need to import global variables and save this much and let's navigate to the ad product screen to navigate. Uh, of course we need to create a named route so we can static constant string, route name, equal to slash ad product. Now let's register this so we can go to router.dot, create this and pass in, add product, screen dot route name, and even your ad product screen.All right now in the post screen, whenever we click on this, but we want to navigate so we can create a function over here called why navigate to our product. Pretty simple, just not mixing our UI with our logic. So just creating it at top. Even if you create it inside of this anonymous function, it won't matter. But I just like to do it this way. Then we will have navigator push name and pass in the route. Name, route name is add product, screen dot route name, take this navigate to add product, pass it in the on press and save this much, restart our application. And if you click away, we go on the next screen. Now in the next screen, we don't want this. Instead. We just want a simple title. So now let's close all the other file and work on this. So via in the title, we are going to replace this entire row with just a constant text widget saying, this is ad product.We need to style this with a textile, which has color of black. Now, if you go, you can see it's pretty similar to that. Now the next thing we need to work on is this container. Now this container looks very different from what we have created so far and this, because, and it is simply because this is bordered and all of that stuff. So for that, we are going to use a plugin known as dotted border. So this is the package that we're going to use. Let's copy this, add it to the dot. Using do dependency. Let's top our app execution. All right, now we can run the app again, run our debugging. And in the meantime, what we can do is first of all, minimize this app bar and now in the body, we will have dotted water. But before that, as you can analyze, we have this image and then we have this product form fields. So for that, obviously we are going to create a form. And there's a possibility that this might overflow because every screen is going to be different, but our sizes are fixed. So what we can do is wrap this with a single child scroll view. So here I'm gonna have single child scroll view pass in the, the child and the child is going to be a form whose key we are going to create in a while, but we will have a child. And the child is going to be a column whose children and the very first children, child is going to be a dotted border. Now we have that. So let's create dotted border and it's going to have a child which will be simply a container. So in this container, we will have, first of all, some properties defined. So width will be as much space as it gets radius. Sorry, high eight will be one 50 decoration will be box recreation with border radius as border radius dot, circular 10. So that, you know, we get some border radius. It's exactly what we are seeing. Then we have a child aware which will be a column, and this column will specify what contents are inside of this, the folder folder thing, and select product images. So what we can have is children, and it'll be constant. I can, I icons dot folder open with a size of 40. After that, we are going to, again, leave some space. So we have size rebox as hide 15, and then a text, which will be not constant because you're going to use a shade color. Because if you see a wire, this is not even gray, not even black. This is somewhat of a shade of a gray. So we are going to use that. So it'll not be a constant anymore. So we have select product images pass in the style, which will be textile with a font size of 15 and color of colors dot gray shade, 400. You can see this is not a cost anymore. So if I save this much and go on this screen, you can see, uh, dotted water is operating well, but we need to leave some space from your, and from your, but if you analyze the screenshot that we have with us, you can see there's some spacing left from your, and there's some left from your as well. And even from the other side. So my point is, if there is spacing left from all the sides, what we can do is wrap the column only with a padding widget makes sense. And then we will specify that we wanted symmetric and in the horizontal direction we wanted, let's say 10. Now we have that spacing done. Now in the column, we will leave constant size blocks, height 20. Now we have that left as well, but still it's not logging, uh, really cool, like this one. And that's because we need to specify some properties to make it look good. So yeah, we're gonna have some properties in the dotted border, like border type as border type. If you pass in circle, it'll create something like a circle, but we want like a, so yeah, we have it. Then we need to specify the radius, which will be constant radius dot circular 10. Now you can see the curves are appearing pretty well after that. We need a dash pattern and it accepts double, which will be 10 comma four, and obviously put in a cons because it's a list of Inger. Now, these dashes appear very well after that. We will have stroke cap as stroke cap round. You can see it's appearing pretty neat. Now, after that, we just need to push this in the center. So that should be fairly easy with the column using main access alignment as main access alignment center and boom. Yeah, we have, it looks insane. Now we just need a couple of text fields and this text field we can reuse because our custom text field is also the same look. So let's quickly copy it down. So let's create first a lot of spacing. So we will have a height of 30 because you can see in the start, there's a lot of space. Then the space decreases. Now we will pass in custom text field, pass in the controller and hand text. So now we will pass in and create a couple of controllers. So we will have final text editing controller as the product name controller, which will be equal to text editing controller. And let's remove this and pass in text editing controller. After that, we can copy it four more times so that we have a description controller and then we can have price controller and then quantity controller. And I think that much is enough for the text editing controller. So obviously we need to create a dispose for them. So let's dispose them before we forget, let's take this product name controller call dispose on them then a couple of more times, so we can pass in this, the price controller. And finally the quantity controller. Now we can go down, pass in the very first controller, which will be product name controller, and then pass in the hand text, which is product name, make sure to add not a very descriptive he text because our validation is based on this. He text, you can see enter your product name or whatever letter you want. See now, after that, we want a constant size box again, and now this will be smaller. So we will pass in 10. Now we can just copy this format, paste it in again, and this will be well description controller.And now we will just say description, save this much. And yeah, we have it. Now the problem with description controller or the description form is that this is bigger because description can be bigger. So for description, what we need to do is make sure that the max number of lines that a text field can add is bigger. So what we can do is go to this custom text field and now add another input of final end max lines and require this dot max lines. Now, the problem is that if we require it everywhere, you can see there are errors in our ad product screen, and even in odd screen, because we are using custom text field everywhere. Now, suppose we have a very big tech, uh, code base now. And if we want to make this change, it'll ask us to, uh, put in max lines everywhere. And we are already happy with what we had earlier. So how do we fix this? Well, we can just remove this required and set it to the default value of one because everywhere the max number of lines was one because by default, max number of line is one. Now in case the user enters the max lines, it'll set to the value, the user enters from other class. Otherwise it'll take in the value of one. So now I can take this max lines and pass in max lines from the construc area. Now your IPA max lines again, and pass seven now. Yeah, we have it. You can see description is now longer. Now similar to the product name. We are gonna have several more fields. So let's quickly add them. I think two more is enough. We need price and quantity. So let's quickly put them in and same for quantity. So we have quantity and person, quantity controller. Now we have everything. Now, the last thing we want is a dropdown menu. So whenever we click on this dropdown menu, we want a list of categories that are available for us. So now let's create them. So we will have sized box, which will take in all the available space, because if we don't specify this, it'll only take in the amount of which it requires to put in this text mobiles or whatever. So it'll be only this much small just me, just let me demonstrate it to you. So it'll be only this much long. We don't want that. We want uniformity. So we will just pass in this big. So here we are gonna have a child of dropdown button, which had provided by flatter. Now we will have value and the value will be the items that we create at the top, which will be the list of the product items.So here we can create list of string called product categories and then pass in mobiles essentials, then appliances, books, and fashion, make sure to use whatever, uh, make sure to properly name them according to our global variable. So if we go over there, you can see mobiles essentials, appliances, books, fashion, make sure to have all of these categories. And these are very essential for our app because based on this, we are going to store the product categories whenever we store the products and this will play a huge role. So make sure to not make any typo. So now we can go down and I value, first of all, is going to be the category. So let's create a global variable called string category and set it to a default value called mobiles. Because here you can see in our app, we have already put a default value of mobile. So whenever the user clicks on the screen, the first category or the default category is mobiles. So now we can take this category as a value. Then we need an ICAN. So the ICAN is going to be a constant I icon of Ikes dot dropdown, actually Ikes dot keyboard, arrow down. And then we need to pass in the items, the list of items that we want in our app. So now that items, if you hover over, this is a list of dropdown menu item object. So what we need to do is what we have done earlier with the carousal. We need to map through the product items that we have. So product categories, dot map, then we have string of items that we get, and then we want to return this drop down menu. So we will have return drop down menu item. And now if you are very confused with the error that are coming in, what you need to do is change it to dot two list. The error goes away. And now in the child, we are going to have text or saying the item that we have right now because we loop through it, right?So product categories is a list. We map through them, we got a single item, and now we are displaying that item for the Semino. And now we also want to put in a value. So whenever this has changed, you can see there's an non-change property that we need to add. So whenever we click on this, we need the value to be assigned, right? So what is that value going to be? Well, it's just going to be item. And that's why I said that this is going to carry the product categories list that we created. Their names is going to carry a lot of value. And finally, after this, we need an unchanged property so we can create unchanged and we will have spring of new value and then just set state to change category equal to the new value that we received. And we are pretty sure that it's never going to be Nu because every value, every time we click on a trip, do down menu item, it's going to return some value and that's it. So yeah, we have the mobiles. If you click on this, you can see list of options that it gives us. And if I click on essentials, now it's essentials and that's because of the on change property. We rebuilt the whole screen. Cool. And finally, after the size box, we will need another size box so that we can create a button. So a button is going to be pretty simple, a custom button. Now the text is going to be sell and the on tap is going to be the sell product that we need to create right now. So yeah, we have it. The UI is now created. Now the next step is to create the API, to sell a product. Let's create that, but actually before creating our own API, what we need to do is be able to click on a, on this and be able to select an image for exactly that we are going to the.dot file. And here we are going to create a utility function called pick images. This will help us pick images simple. And now I've named it pick images because we are allowing a product to have multiple images. So it'll be a list of file and it'll be images which will be empty. Then we will have a try and a catch block. And here we are not going to display a short snag bar. Instead we are just going to print it out because there are very less conditions in which we are going to get any error. And whenever we get this error, it's mainly because the user does not select any images. And that's not a correct way to show the snack bar because if the user doesn't show images, we don't need the snack bar and also remove the dot HTML import and instead do.io because dot HTML only works on web suite. So now in the tri block, we need to select the image for, to select the image. We need to install a plugin file picker, or you can even install image picker as long as you know how to use them. There's not much difference in both of them while picking an image or selecting an image. So let's add that dot add dependency, put in file picker, and I'll save this file for now. Stop a app execution and see if there's any installation required. So here in the installation and set apart, we can see, we need to do something for Android, IRS, web, desktop, or anything. So here you can see Android all said, you should be ready to go as long as you can see runtime permissions. So, yep. It's all good for us after that in the iOS, it ask us to, well, use all of this in case of the file type that we are using. So we are using file type image. So let's find one for that. And here we have it. Whenever we use file type dot image or file type.video, we need to add the following key. So let's click on this, copy it, go to our info dot P list file and add it. Make sure that your info P list file is in the iOS, not Macs pasted down your, and then you need to explain why our app uses the photo library. Well, we want images, right? So we can just write. We want image for product and you need to definitely write something that is very more formal. But I think for me, since I'm not uploading to play store or app store, that's fine. So now I can rerun my application. And while that is happening and actually, while the app is launching, now we can in the tri block, add a wait file, picker dot platform dot pick files. And now we need to pick files. Well, first of all, mention the type which will be file type dot images. So that it'll only show us the images of the type file type, sorry of, uh, files of the type images, sorry, after that, we need to make sure that we allow multiple images to be selected. And yeah, we have it also just remove the extra sor put a semicolon after having that let's toward them in a variable called files, and this will be of the type file picker result. You can see that we have file picker result. Now with this file picker result, first, we need to check if files is not equal to Nu, we saw that it can be Nu and we know you need to check that files.files.is not empty. So the files list that it gives us is not empty. So if this is the case, that means file is not Nu and files is not empty. Meaning the files, which is the variable dot files, which is a property, which file picker result gives us is not empty. So if it's not empty, then we need to go to and do four. And I equal to zero. We basically need to map over all the files way up. So you can have files dot files. I is less than files.files.link I plus plus, And then add all of the files that file picker has to our images. Two are images list. So have images.ad path and file, which will take in a path which will be files dot files at I dot path. And here you can see the argument type string can be assigned to the parameter type string. So we can just put an exclamation mark away. And finally, we will return this images list. And then finally, we can give your, you know, a future list of images or the file as a return type. Great. It's always good to have the return type of error because later on when we use this pick images, we won't know what the return type is and it'll be dynamic dynamic. Isn't a very good thing in the R product screen, we can create a function called void select images, and this will be asynchronous again, here we will just say, result is equal to of eight pick images and we need to import it from the utility file. Then we need to set state Of images, which is not created. Yes. So we will create list of file, call images and set it to an MD list. We will also input this file and then we will have images equal to result. Now we can take the select images and wrap this around this dotted bottle. So we will wrap it with a gesture detector and on tap, whenever we click on this, we want pick images to run. So yeah, we have it and actually not pick images, sorry. We want to run select images, which is a function that we created away. Pick images is a function in the utility file. Sweet. So now let's restart our application, click on this floating action button, click on select product images, and here I'm able to select the images and I can select multiple images. If I click on add, I don't see any error. That means it has been successful. And images now has this. So let's try to display those images on the screen for that. We are obviously going to use carousal slider again. So for that, we can just copy it from our carousal image dot file. We could use this function in case we were receiving items from the constructor, but you're not doing that because we've created that in a separate feature. Now I'm not saying we are not going to U reuse some features widgets, but in this case, let's not do it in case we want the products to show up differently where it's great to have a different, you know, widget shown away. So here I can check if images, the global variable that we created is not empty. So if it's not empty, then we need to obviously show the carousal slider, otherwise a gesture detector.So we can paste it import the carousal slider, not carousal options. It'll only import this, but we want carousal slider as well as carousal options. Then we can remove this carousal slider, save it and see what the is. Let's remove this. Yep. Looks right. And also remove this global variables dot carousel images. And instead add images dot map this. After that, we DEC receive a, a file over and now the file is not going to be image.network. It is going to be image dot file, which is another widget so that we can display a file. And if you save this, you can see the images are showing up just with the hot reload and everything shows up cleaner. And later now, finally, we can go to the API request where we can create our API. So now let's close all the same files. And in the admin, we are going to create, um, another folder called services.And here we are going to have admin services five. And here we are just going to create a class called admin services inside of which we are going to have several folders. And the very first function that we're going to have is sell product. Now this is going to require a lot of things. So let's give it a named cons named parameter. So we will have build context, obviously, just to display the errors. Then we will have a name which is the product name. Then we will require the description, which is a product description. Again. Then we have a price and this will be in double because the user can enter digits or decimal points. Then we can have quantity, which will be double as well. I mean, you can have interior as well. It won't be a problem, but I'm just gonna go ahead with double. Then we are gonna have category. And then finally a list of file. Let's copy this. And this will be called images. Now I'll import this from do IO and here, this is going to be asynchronous and put a tri block, obviously aware. We are going to show a snack bar, so you will have E two string. And now the very first thing that we need to do is upload the images to the database. Now we could have done that in the server side, but doing it in the server side is less easier as compared to doing it in the client side, using a plugin, which is provided to us, first of all, where are we going to store these images? Now we can't store these images in Mongo database. You can store them, but I think it's very difficult to store them. And I would not recommend doing that because we have only 512 MB of storage given by Mongo DB, because we are using their shared cluster. So instead, what I would recommend you to use is Cloudinary. This is the website for cloud d.com and this is their client sided usage. So we can use cloud instead of sending HTTP requests to this cloud, uh, storage. What we can do is use cloud public, which as it tells here, allows us to upload media files directly to cloud without exposing our API key or secret key, which is huge. So now let's quickly log in and you would've to sign up in case you're coming for the first time. Actually I'll also sign up. So you need to enter your name. I'll enter R then I'll enter my email after entering the password and the email, you don't have to enter company site name, then you, you need to enter a product. So we can just write program media for image and radio API, click on robot and click on create account.All right. So after confirming the email, your become welcome to cloud, what's your main role. I'm just going to say, developer, click on continue. Then we need to build a new website. We can click on done and here we have it. Now let's first of all, delete all the samples. We don't need them. Let's click on refresh. We have all of these samples still there let's quickly delete all of them. And then here in the settings, we need to get two things. First of all. So actually let me tell you why we need them. So here we can just take this cloud in the Republic, add it to our dependency. Let's stop our app execution. And now let's create an instance of the Cloudinary. So let's run our app also. So here we have final Cloudinary equal to cloud public, and let's initialize that where in the constructor, it asks for a cloud name and the upload preset. So for cloud name, what we can do is go to the dashboard and here you can see, this is the cloud name. We can copy this, paste it here. And then it asks for upload preset. As we saw, we don't need API key or API secret key anymore. So we can just click on settings and get our upload preset. So to get the upload preset, yeah, we need to click on upload, go down, enable unsigned, uploading, delete this signed uploading. And then this is our upload preset. So we can copy this upload preset, go to our dashboard again, and your pass in the upload preset as well. Now, make sure to not use whatever I'm using and create your own account because I'm going to be deleting everything after this tutorial. Great. So now we have a file list of files and it is called images. So now I'll create list of string called image URLs. And what we are going to do is essentially map through all of these images and send it to this Cloudinary storage. So we will have four N I equal to zero. I is less than images.link I plus, plus then we will have of eight cloud dot upload file. And you can also refer to their documentation here, which clearly states how to go ahead. Your it is written. So we need to upload file. And as we saw, we Cloudinary filed or from file is what we need to pass in. So we will have Cloudinary file, not from file. It gives various options like from bys, from, from URL, from future, by by data. But we will use from file because we have a file and then we will have images at I, and this is a file. We'll use that files path and store it over there. Now we will just use cloud in a response to store it in a response variable. After that, we can just use images, image, urls.ad, which is this list of string and add the response dot secret URL that it gives us so secure URL. So this is the download URL that we get from file base or the upload URL, whatever you want to call it. Now we have access to this so we can send this to our API, but before doing any of that let's. So now before moving ahead, there's one thing that I would like to tell and one change that I would like to make. That's simply we store all of the files away, but you can see if we store it it'll store in our, in our media file library and it'll store it here continuously. I mean, there has to be some management in our uploading as well, right? Let's make a folder for this. It won't create a folder by default. It'll just store images like itself. So here we can pass in the folder. So every product that we have will have its own folder inside of which we will have several images. So here we can pass in the folder as a name of the product and save this much. Now we can go ahead. We are not able to test it yet because we don't have all of this stuff. So now let's create a product and finally upload it to our MongoDB as well. Now we will be uploading only URLs to our MongoDB. So now, first of all, we have to create a product model. So let's quickly create that product.dot. So it'll be pretty simple class product, whatever we have accepted from the structor, that's all we need. So we will call it final string name, final string description, finals, double quantity, final list of string of images, and make sure to not use file away. We are storing all the download URLs away. Then we have final string category, final double price, and year we will also have string, which can be nullable called ID a string, which can be nullable called user ID. All of this. We are not storing right now while sending data to our server, but we will store when we get data from our server. And we will also have rating, which we will create later on after we add the rating functionality and make sure to add the final keyword for both of them as well. Now we can create a constructor then Jason serialization, and like earlier, we made changes for the ID in the, from map function. We can pass in map, underscore ID aware. You can see in our user dot file as well. We have passed in map underscore ID aware and similar to that, we have map underscore ID in the product as well, because you're not passing in the ID. Mongo or Mongo database is going to create it for us. Having that in place, let's create a product model over you. So we will call this product and now we need to pass in the name. We have it description. We have it quantity. We have it images. We need to pass in the image, match, URLs, category, price, and all of that is done. There's no need to enter rest of the things that it has, for example, ID and user ID, because they're after that, we just need to post that. But before doing that, we need to create that API. So what we can do is go to a server and here in the routes, we are going to create admin JS route. This will contain all the admin dot JS functions. So obviously import express. Then we need to create an admin route, which will be equal to admin route, uh, which will be equal to express router as a function. And then we need to create a post function so that we can add a product. Now, before starting with this, there's an exercise I would like you to do well. It's just creating an admin ware. Like we have this Orthodox GS middleware. We need to create something like an admin middleware. What different will be admin middleware. It's basically you are. The only difference that we need to make is get, we have the ID. We need to get the user by their ID and check if the type is admin or not. That's the only thing similar to the oath Middleware. So try it on your own. If you can do it, then let me know in the comment section, otherwise we'll do it together. Were you able to do it? If not, let's do it. If yes, let's verify your work. So you're in the middleware. We are going to create admin JS. Then we are going to require JWT. So we will have Jason web token. Then we will create a function called admin, which will be asynchronous and we'll give request response. And next we will already understood what all of them are. We need a try-catch block. And instead of writing all of that, let's take in the inspiration from oath. You should write it on your own, but since I'm already familiar with how to go about it, and I've written it multiple times before, before even creating this tutorial. So I'm just going to copy paste it. So over here, after if it's not verified and we are setting user to verify.id and all of that here, we can get the user by their ID. So we will have constant user equal to of it. User dot find by ID. We will pass in the verified.id also get user. So we need to require user. So we will have constant user, which will be equal to require dot slash models slash user.Great. Now we have that user. We also have awaited it and we can use our weight because it's an asynchronous function. So here we can check if user type we already have that. So if we go to our Mongo database, you can see if users type is admin. So here we are just checking if it is user or the user type is seller, then we need to return a status saying 4 0 1. This is unauthorized saying with the message. You are not an admin and admin. And if it is an admin, well obviously request user request token. And yeah, we have it. Great. So now we can create the post route. So obviously let's add a comment of adding product. So we will have a post route which will be called slash admin. Now we have already used API, but it is for a common user for admin. We're going to use slash admin slash ad product. And in case you want to extend this app further after this tutorial and you don't, you want even those sellers to be a normal user. What you can add here is oth instead of creating an admin metalware, but we are allowing only admin to use that. So obviously import admin, which will be Slash middleware slash admin. Now we've passed or admin as a middleware, and you can add as many middlewares as you want. You want 2, 3, 4, you can add them. So obviously we'll have asynchronous request response. Then we have a try and a catch block where we are basically going to return res dot status of 500. You should be familiar with this by now. We are just making use of this again and again. So it should be a good practice for you. And here we have to get some things from request your body. Obviously we already know how the format of this is. So now we can have name, description, images, quantity, price, and category. Now, just to remind you these names over your should be matching to a product dot file. When we convert it to map, you can see all of these should be matching to what we pass in in the routes. Great. So now let's create a product model. So now we have to create a product model here as well. So we have product JS and similar to user model. We're going to have all of that. So let's paste it down here, call it product schema. And now we will just have this much before we forget. Let's create a model for this, which will be product. And it'll equal to Mongo dot model pass in the model name, which will be product. And this will be the product schema and obviously exported, which will be equal to product. Now, before forgetting all of this, let's do it right here itself. Now let's define schema. So first of all, we need a name which will be of the type string required set to true and trim should also be true. Then we need a description which will be of the type string required. Again, set to true and trim. Again, set to true. After that, we let's add images. This will be an a, so now, till now we have not stored any, a anywhere in our application, right? So to store an a, what you can do is obviously create like this type of string type of a sorry like this. But instead of doing that, we are using something fancy, aware. We are using list. And this images list is going to consist of Properties, which will be type string and or will always be required. So it'll be set to true. So you are, we are creating an area of images which have these properties after that, we need a quantity, which will be obviously a number you can't pass an <inaudible> or anything like that. You need to pass in a type number or otherwise you can just pass an N 32 a or end something like that. Then this is also set to true. Then we need a price which will be of the type number again, and will be required. Let's rename this to number again, after having quantity and price, we need category the user ID. We are still left with that. So obviously type string required. True. This is a category which is mobiles or whatever. Then finally, we will have the user ID, which will store the ID of the user who sold this. Now I don't think it is needed. So let's remove this. What my idea initially was that we would create user ID, which would store the idea of the admin who sold this. But now, as I'm thinking, I think we will have only one admin in this application, which will be ourselves. So there's no need of storing user ID. So we can, again, go to a product.dot file, remove the user ID, remove this user ID again, this and this, and we are good to go. So again, we can go to the products and finally, we are going to have something known as ratings, but we will reach there later on. Now we have all of this. So let's create a product model which will be let product equal to product. We have imported that and it'll be a new product, obviously. And then we need to pass in, in the object, the properties that we need. So obviously name, we know the shorthand now, description, images, quantity, price, category, user ID is not there anymore. So I think all that is there is this. If you go by, you can see name is needed, description, images, quantity, price, category, all of that we have passed in. Now we need to save it to our database. So we will do product is equal to elevate product. Lord save. What we are doing here is basically using, let, let, will make us change the variable name later on or variable value later on. If we use constant, we know that from flatter as well, if anything is constant, it can't change later on, but with let it allows us to change. And here we are basically creating a new product and assigning it to product. Then we are saving that product, which is a model and it gives us a function. Do we are saving that to Mongo database and whatever Mongo database returns to us, which is, uh, a product within underscore ID and underscore underscore version that we are saving in product so that we can return product to our client site. So now we could test this API using thunder client, but instead of doing that, what I'm going to do is directly go to the Ironman services dot file, and you're directly create a post request to check in our application itself. So I'm going to import HTTP as HTTP. Then we will have http.post. We have to pass in the URL, which will be dot pass URL, which will be dollar from our global variables slash admin slash add product pass in headers. So we have to pass that outside this. So we will pass in the headers because this will be only by authenticated or authorized users, because this has a functionality of Art middleware. So obviously we need to pass in the headers. So let's copy the headers from one of the files. So we have art service and let's find the headers. Yeah, this header, let's go here, pass in this header. And finally we need to pass in X or token, which will be from the user provider. So let's create the user provider at the top. It's not an asynchronous function, so we can create this other top, calling it provider.off user provider context, listen, set to false.And that's it. Now we can take this user provider and use user provider dot user dot token, which can never be Nu. And finally, don't forget to pass in your body because headers are different. We are PA we are authorizing ourselves using this header, but with body, we are sending the data that we need. So if you go to admins, you can see authorization is done using admin middleware, which looks at the request dot header. But here we are looking at request dot body. Those are two separate things. So now we need to pass in body, which will be product, got two Jason. After that, we need to do error handling, which will be HTTP error handling, and we need to pass in response. So let's to this in the response call response as equal to innovate HTTP response GTP post. Now we can pass this response. And in on success, we can display a shown bar saying product added successfully and then navigator dot pop, so that we go back to the main screen. So if I restart my application now and before doing anything else, let's bind the sell product to our posts, actually our products free. So now we will create an instance of the class. So we will have final admin services is Equal to admin services. Now take this admin services, call void, sell product. Now obviously we need to validate a form. And for that, we are going to create a global key for that. So we will have, let's say final underscore add product form key equal to global key of form state, and use that, that add product form key in our form. So let's go down to our form and here use the key, add product form key. Now we will be able to use the validate function so that every field in this screen gets validated. We have already looked at it in our file. If you forgot about it, it's a good way to remember about it. So now it'll give us a bullion value to validate. And if the form is correct, all the fields are being passed in. Then we can say admin services dot, sell product pass in the name, which will be well product name. So let's quickly type in product name, controller dot text. Then we will pass in description, which will be description. Controller dot text price will be price controller dot text quantity. And actually this requires a double value. So what we can do is double dot pass. And since this is a string, we can use double dot par. So passing this. So we have this done. Now we can copy this page straight over here and do the same for quantity controller. And here we have it sweet. Now, before even validating the form. One thing to note your is that if we validate the form, it'll not think about this image that is there. So here, we also need to make sure that the VI images that we have is not empty. So we need to make sure, and actually instead of a, or we need to do. And so we need this form to be true. That means all the controllers that are there should be fair. And the images list that we have should not be empty after doing this much and using the cell product down in the on tap, we can pass to it, the cell product and restart our application. Now let's see how it works around. I'll select some products. Let's say I select a few iPhones. You can see I'm able to select them. I'll call them iPhone 13, pro one twenty eight GB. I'll give some description. Let's say great iPhone for great people. I don't know, man. I, no, man, this much. So then in the description we can say, good phone must buy totally worth it. And yeah, now we can pass in the price thousand dollars quantity we have is 20 and it's in mobile section. So now we can click on cell. Nothing is happening and you can see, we got an error, cannot post slash admin. Now, anyway, when, whenever we get this error, it, we should be sure that the URL is correct. So we have that. <inaudible> other thing that we should note is that this admin router should not, should be connected to our index GS file so quickly export it And then use it in the index GS file using app dot use admin router. And here we need to save this and we are still getting an error. The reason for that is if we go to our admin router and in the admin, we have not exported this. So let's quickly export this. So we have moduled or exports equal to admin. I usually forget that. Now, if you go where connection has been successful. So now let's restart our application and all the data has now gone. So I'll quickly fill in and then see you. So I filled in all the details. Now I can click on sell And you can see product added successfully. Now there are no errors of even in the DB console, there are no errors. So now, if I just refresh my database to see a new collection, which is products, we are the user's collection, which consisted of all the user data here. We have the products collection, which consists of all the products, and this is our very first product. It consists of images and you can see our secure URL. If I just click on edit to grab one of them and paste it in the browser, you can see via Ania. Also, just to show you the folder management. If I click on refresh, you can see iPhone 13 pro one 20 at GB. Both of them are the same folders, but this consists of all the URLs. And this came in two times because There was some error in our script, but still it's fine. This won't happen and repeat again. But yeah, we have it, our four files showing up. So now our data is getting stored. The next step is to display them over on this screen. It should be very, very easy for us to do it. All right? So now what I want to do is close the terminal, close all the safe files so that it looks a bit cleaner and a lot less messy. And now in the admin services file, I'm going to go down and create a new function to get all the products now, to get all the products let's, first of all, create our own API to create our own API. Obviously let's go to the admin JS file. And this is your fourth exercise to get all your products by all. I mean, literally every product that is mentioned, I want, we want that so that we can display it on this screen because yeah, the admin, right. And the API name that we want is slash admin slash get products pretty simple. So please try it on your own and then we can do it together. Were you able to do it? If not, we can do it together, otherwise follow along. No problem. So your admin router dot jet should have slash admin slash get products and make sure to get, make it as a get request, because this will not be a post request. All we are doing over here is just fetching the products. We don't need any input from the client side, right. We just go on the screen. We see the products, no input is given. So yeah, that's it. Now we need an admin middleware because only admin should be able to access it and then obviously request response and yeah, that's it now where we have our TRICA block and then we should have race, rest status, 500 Jason. And the Jason that we will pass in is the product, sorry, the error saying E dot message. And in the tri block, what are we going to have? Well, we are going to get the products and it's fairly simple await product dot find. And then we don't pass in any criteria of what we need to find using find, as we've seen before, it'll get, give us a list of documents, of whatever ID that we pass in. For example, if you want to pass in, if you want to get a particular ID, then what will we do pass in ID over here and pass in the user's ID like this suppose this is the user's ID. If you want the, uh, let's say Product description. So with their description, if their description is again, Ania, then we can get their description using that. And it'll fetch us all the products in an I, which are with this Ania, but here we are not specifying only what property we need to find by. That means it'll get all the products that we need. And then simply we just need to return that to the client. So we'll address George Jason products, and that is our get products route. Pretty simple, just a bit of logic was required in that. And obviously we are going to fetch all the products and what we are going to do over here is quite different from what we did earlier on here, we are going to return list of products by converting them. For example, we send the Jason product survey, right? We are sending the products data back to the client side. Here we, in our client side, we have access to the product model with that product model. We are also able to convert any Jason format that gives us into a product model. So you to use it in a app, you're going to return future list of product because you're going to get list of product in adjacent format. And this is obviously going to be asynchronous and thus, we will also need a try and a catch block.And then we are just going to return a shown bar with a context and the string that says E two string. Obviously we need to pass and build context over so that we can appropriately show snack bars. Then we need a user provider because we know we need to get the token of the user. So we have final user provider equal to provider dot of user provider context dot. Yeah, that's it. Then we can create a list of product as well, outside the tri block. So we have list of product called product list, which will be empty. Now this product list will get some data as soon as we convert the Jason to a product model. So for that, we need to send a get request. So we will have HTTP get pass the URL, which will Beri dot par dollar slash admin slash get products, a lot of boiler plate code again and again, you're writing so that you're familiar with what you're writing and you know, it becomes a practice to write this way. After that all we need is headers because authentication is still needed. We don't need to add any body, but authentication is still needed. So obviously we can copy these two headers, paste it in over here and save this in a variable. So we will have Response response equal to this. And then we are going to handle this error. So we'll pass in response. And then on success, what we need to do is convert this Jason format that it gives us the response dot body, whatever Jason format it gives us. We need to convert that to a product model. Now, as you can see, we are going to get list of products in Jason format over here. Also, we are finding products and it'll be list of products. So what we need to do is run a four loop so that we can get each and every product that we have. So we will have four. I equal to zero. I is smaller than Jason decode response dot body. If we just do response.body.link, it'll give us like 100 characters or so, because the response dot body is a string and we're getting that strings link. But in, if we do Jason decode, it'll convert it into a list format that we want and grab its link. Then we will just do I, plus plus then we will just do product list.ad, which is this. And we need to add product over here. So, well, first of all, what we need to do is product dot from Jason and enter the product. Now, what is the product going to be response dot body, whatever it sends us at a particular index, which is this four loops index that we have. But you can see from Jason excepts, a string. If we use Jason decode, it doesn't give us a string. So what we need to do is rather this Jason, from Jason, with Jason in code, and in that we'll have Jason decode so that we can pass in response dot body at particular index. I let me format this so that I can explain it to you again. If it's not clear, basically what we are doing is we are having product list, which is a list of products and empty for now. We are adding them. Then we are using product from Jason, which we got from Jason serialization. When we created a product model, then we are converting it. Let's say we are converting it over here. We have response to our body. We are converting that into a map or a format using which we are able to get the products, Jason, a particular products, Jason, at that particular index, since we are looping it. And then we are encoding that because from Jason accepts a strength source, we can't just pass in Jason decode, right? So if I just try to do this, it's not great because it'll give us an object. So now it's not giving any error because Jason decode is other type dynamic. But when we run it, it'll give us a runtime error because from Jason will accept a string. Jason decode will not give us string. Finally, we will use Jason in Cordova so that we can use a string and it converts adjacent to a string. And then we are converting it into a model and adding it to a product list. Great. This was a bit of twist and trick, but that's cool for us. We can solve that after that. We just need to return that product list and cool. We are done. Now. We just need the switch, all products to run whenever we start the screen.So now we need to go to the post screen. And if you want rename it to product screen and call the init state function. And then here we are going to call fetch or products. And we can't turn that function of admin services. This function over a year in the innate state because innate state cannot be turned asynchronous. If I do it over year, it'll not give us any error, but in the runtime, it'll give us error because in state can't be asynchronous. So to avoid that, you can either do it and change dependencies. Otherwise you can just create a separate function, fetch all products, which can be asynchronous later on, and obviously create an instance of admin services over year in case you're wondering why I do it globally every time. That's simply because if we have more admin services feature that we want to use, we don't have to use admin services dot, fetch, all products or anything. In that case, we can just use Ironman services instance and get all products. And we've passed in the context and you can see it has a return type of list of products. So let's await it. And also to display it, we will need a list of products to show up. So what we can do is create list, list of product, which can be nullable called products. And this is nullable and not empty because here we need to show a loading bar. As long as we don't Fe the products, which can take some time, right? We are sending, we are getting data from the server. So as long as the data is being fetched, we want to show a loading indicator. Now, whenever we fetch all the products, you might see a bit of delay now to put that loading indicator, we are going to check if it wasn't an empty list, if it was an empty list, I suppose we are going to check.If products.is empty, then we are going to show a loader, otherwise this, but the thing is initially even if fetch all products doesn't have any product. For example, before we have added any product that you, the element is using the app for the very first time, and there are no products at all, even then the products list will be empty. So that will cause our app to continuously show a loading indicator, but that's not the case. We have already fetched it. That's why we are using Nu type layer so that we can check if products is equal to Nu, that means that the data has not been fetched. And if it's empty, that means that the data has been fetched because list of product is always going to return product list. Uh, if it's empty, then it's not going to add and return and empty list. At least now let's create a constant aware called actually a widget aware called loader.dot. And we can import material dot for that, create a state list. Widget called this dateless widget, call this loader. And basically we just need to return a centered child showing a circular progress indicator. Obviously mark this as constant, nothing else is needed. You can specify the color of this and all of that in loader. But in our case, we've already said in the main door dot the theme of our application, and that's exactly what we want to show. So we have the loader Pass cons and actually remove this colon sweet. Now, still it won't show us anything. And that's mainly because, well, we need to run set state so that it fetches all the products, which can take some time. So after the widget has been rebuilt completely, you know, it'll show us the loader and then it'll set state that yeah, the loading part has been completed. Now let's get our terminal and restart our application just to see if there's any error. And now you can see loader is continuously displaying. The reason for that is pretty simple. You can see the error showing here as well. Your in provider, we have not set listen to faults, even if, even since we are outside of this post screen, you know, build context function. So now let's restart our application and we are still seeing this loading indicator. The problem again is that we are fetching all the products, but we are not saved it in the products variable. So let's quickly save it and restart the application Here. You can see, we are seeing this again. We can restart the application, we get it very quickly, but for a very small time, you could have seen the loading indicators showing up. Now let's display this products on the screen for that. It's pretty simple. We have the body here. We just need to replace the body with whatever we want to show. So first of all, we just need to show a grid view builder. So here we have the design of our application. This is how we want to make it. Well, you can see this is the design and this design might seem very similar to the single products that we had created. If you remember, we had created single product.dot widget product widget. We are going to reuse this widget over year, even though it's in another feature, it's pretty good. We are just going to reuse that feature everywhere now. So first of all, we need a grid delegate. So the grid delegate is going to be constantly a grid delegate with fixed cross access count. Mainly how many products do you want to show on this? Uh, in a row side thing in horizontal direction, how many products do you want to show? Well, I just want to show two.And then the item builder, which will give us context and index and we go into return something. So now in the item builder, we are going to get first of all, the product data. So let's save it in product data, variable, product data, equal to productsWhich can never be null index. And we are saying, and we are assuring that this can never be null because we are already checking your, if the product is null, we are going to show the loader and it'll keep showing the loader as long as it's not. So here we can be sure that the product is not Nu. Then we need to return a column. We are not returning just a product, single product, because it's just displaying to us. The list of the products is right. I mean, sorry, the image of the product here. We also need to display the text and the delete I icon. So for that, we are going to return a column With children and the first child is going to be of the size box. We are going to give it a specific height of one 40 saying this is a child, which is the single product. Now single product will receive a type of image. So let's pass in the image, which will be product data dot images. At zero. You can see that images can be a list of string, but we only want to access the very first element on that because we can't display a carousal image on that. You know, it, it is going to look very viewed. And now finally we want a row so that we can display the text and the delete. So let's quickly create a row with some children and obviously main access alignment as main access, alignment.space evenly. Then the children is going to have an expanded child of text saying product data.name. Overflow is going to be text overflow dot SIS. We have already looked at this logic, so I'm not explaining it again and again. And then max line is two. If you want, you insert it to 3, 4, 5, whatever, but let's keep it two so that it looks good enough. After that We need an I can button so that we can create a delete option. We're not going to create a delete option right now, but we will look at it later on. So we have I cans dot delete underscore outline, and also put a cons where yeah, cool. Now we are getting this error and that error is coming mainly because we have not specified the item count in our grid view builder. So the item count is products.link, and also make sure to pass, not then click on restart. And here we have it. We are able to display the products. Now let's add another product. So we will have a bottle so that, you know, we just have some other category. So let's say stainless steel, less steel bottle. This is good. Non rusty bottle price will be, let's say $30. And the quantity will be 200 and we are going to mark it as essentials, then click on sell. And the product has been added successfully. If you're not able to see it, don't worry. If you come back, ER, you can see stainless tail bottle just need to refresher. Great. All right, now let's just work on the delete product as well. Since we are, ER, I know I said that we will touch that later, but now let's just get done with it. I'll close the loader file and in the admin or yes, let's make this as an exercise for you Create a route using which we will be able to delete the product. I'm not giving you any clues for this. Try to use the functions, which we haven't touched before actually, but you have told to you about it. So try it on your own and let me know in the comments, if you could do it, were you able to do it? If not, don't worry about it. We'll create the API together so that we are using admin router dot get slash admin slash delete product. Obviously we are going to do admin, call this as an asynchronous call back function and have this. Now, obviously this is not going to be get, this is going to be post because we need to send in a body of the idea of the post that we want to delete or the index. So here we are obviously going to have tri cash blocks. So I'll just copy it from here. I'm tired of writing it again and again, and now in the restaurant status, we have T message. But a year what we are going to do is first of all, grab the ID from request dot body. Then we want to find the product and delete it. So for that, I've already mentioned about it. We will use product dot, find by ID and delete. This is the function that is given. So we'll find by ID the product and then delete that product pretty simple. So we'll just pass in ID and then we will do product is equal to automate product save so that we save the updated list in our database. And then rest Jason send in the product that was deleted. Now there's no need for this, but just to send a status code of 200, you're doing this.Now we can come to the admin services class and in year we will create a function called void delete product and like other functions we are going to have required build context, then product that we want to delete and then, uh, void callback of on success. Now earlier we saw that whenever we created a product, let me just type it out. Then I can explain. So earlier we saw that whenever we created a product or fetched all the products and then maybe added a product you saw that we had to refresh the screen. That means go over here. And again, come back to see that new element now to resolve this. What we can do is except from the parameter on success argument. When we do this in the, on success, what we will do is in the post screen, whenever we call this method, we will take the products and remove that product that we just deleted in the database as well. So on the client side, also, we are deleting what the user sees and even on the server side, so on success with the will help us with that because we are not giving the, because if we don't take it from the, uh, parameter, what will happen is we won't be able to call set state let's suppose we pass in the product list, which is this product. We pass it away and then delete the product. But to display it on the screen, again, we need to call set state. We can't call it an admin services. It's not a stateful widget. So for that purpose, we are having on success, passed in through the parameter. Now rest of the things are going to stay pretty similar. So what I can do is copy this, go down again and paste it away up. Now obviously we'll make some changes. Now we don't need to create product and cloud all of that stuff. So let's remove all of that. Obviously we need to put in asynchronous and synchronous and in the headers, we want to pass that, but product, we don't want to send in the product. We just want to send in the ID of the product. We can pass in the product to Jason, but instead of sending that whole, what we can do is just pass in ID. So that will be ID and then pass in product.id. And obviously Jason encode this and there we have it ID send, and we obviously have the headers done. Make sure to add that then in the error handling on success part, we'll just pass in the on success, call back function. Cool. Now we can take this delete product and use it in our function. So here we can create wide delete product. And let me just type it again. And it'll take in product argument, because even here we don't know which product has to be deleted. Only when we click on that button, we will get to know which product has to be deleted and obviously the index so that we can delete it from the client side as well. So now we can use admin services dot delete product. Now context is there. Product is passed in now in the own success. What do we need to do? I would highly recommend you to try it on your own and think about it. Well, it's pretty simple, right? We just take the products and then remove at that particular index that we get it. So in the grade view builder, we have access to the index. So with that index, we will remove that particular product simple. And now we need to reflect the changes on the screen. So we need the build function to rebuild again. So we can call search state easy. Our work is done only if it success, it will remove otherwise it won't remove it. Now we can go down and your call, delete product pass in the product, which will be product Data. And the index is obviously there because the index is the same name. Now we can save this much. And whenever we click on suppose let's say iPhone 13 pro you can see, we are getting an error over here. And we got that error because if we go back to the admin services, we again forgot to change our URL. So let's copy the URL from your, and paste it over here. Pretty stupid mistakes. You're we keep making, but that's fine. Now, if we click on iPhone pro 13, no document found for query this object ID. So that error came in, mainly because if we come back away, we have product is equal to avoid product.save. And we don't need that. Whenever we do product dot find by ID and delete, this will make sure that the product is deleted and the product is saved as well. So now we just need to do this and then we can send adjacent of product. I change all of this just to debug what is going wrong, but now we know the error. We just need to do product fine by ID and delete and then send the product. Now, if I try it again and click on delete, you can see we're not getting any error anywhere. And now if I restart the application, The product is deleted. Now, even if we go to the MongoDB database and go to the products, You can see query results are zero. Now let's add, uh, some products so that we can see them on the main screen when we to the user side of the things. So after this, obviously we are going to move to the Mo user side. We are not going to work in the admin anymore because there are no features to add in admin, as long as we don't allow the user to send the products to anyone. Right? So now I'll add some products like two or three, and then see you when I change it to the user side of the app. All right. So I've added to products there, but I'm still on the admin screen just to notify you that whenever we add a product, you could see that it wasn't real time. Now having the knowledge, how to make it look real time, you can do this for the ad product as well, so that, you know, it looks a good experience for the user or, and also now we can go to the users.I wanted to demonstrate how I'm shifting to the user part. If you've not already noticed here, I'm just changing the type two user and I'm clicking on update and then restarting the application. Your we have it. Now, what we need to work on is whenever I click on one of the categories, I want to get shifted to another screen and display the category, display the products of that category. So for that, we are, again, coming to the home feature, let's minimize all the, the folders and in the home screen, we are going to pass in another screen called category deals screen. Do, do you obviously will import the material dot, call it as a stateful widget because you need to get the products. And now we are going to create a category deal screen. Now over here, we're going to do things a bit differently. First of all, we are going to have a scaffold and that's going to be normal. And then we need an app bar that is also going to be normal. So we can go to the admin screen, get the admin screens app bar. So let's quickly copy that and paste it in the app bar space, then click on import library and in the title instead of a row, we want to display a text that just says that this is this category. And we are going to get category from the constructor so we can write final string category, and this will be required. This dot category. And we are receiving from the constructor so that whenever we click on one of these screens, we get the suppose we click on essential. So we get the essential string and based on that, we can fetch products away. So here, I'm just going to write text as widget dot category, and then the style will be obviously the black color. So let's quickly add that style. So we have style constant textile of color, colors.black.Great. So now over here, after this preferred size widget, we need to add a body and here the body should be a column showing a list of widgets. So the very first thing that we need is seeing that, that the children are container of padding. And then we need to add that pairing. So we have sets symmetric from the horizontal direction we have, let's say 15, and from the vertical direction, we have 10 after that, we have to align them. So we have alignment.top left, and then we need to have a child saying the text and there, this text will basically tell, keep shopping for and the category of that. So we have keep shopping for dollar widget category. And I use braces for that, because if there is like a dot and full stop, and it's not a single word, then we need to use brace for that. Then obviously we need to style this so that we can increase the font size. The color will be black, so we don't need to worry about that. So we have font size as 20, and now just to view it, what we are going to do is whenever we click on any of these buttons, so let's go to the top categories and here, if any of the button is clicked. So here it is. First of all, we have to wrap this video gesture detector. So wrap it with a widget call, gesture detector, and then the on tap is going to be what we tell it to be. So it'll be void navigate to category page, and this will just receive the category that we clicked on because you can't get access to it in the separate function that is created, right? And now we will just say, navigator dot, push named. And I just realized we didn't create a route for that. So we need to go in the category, deal screen and call this static string static, constant string route name, which will be equal to slash category deals. Then we can take this route name and go to the router.dot, obviously past it over year. And this will be called category deals, screen, route name, return, the category deal screen. And this is not and year we need to pass in. So here we need to pass in an argument that is the category. So let's quickly add that now, how do we get access to the category that the user passes in? Well, it's very simple. We just say that category equal to settings and it'll be route settings because our parameter type is your route settings and this route settings dot arguments. And now if we save this, you can see that the type of category is an object. We don't want that. We want it to be a string. So we can say as string, because we know always the user will always enter a string. Now we can take this category, pass it in. And it's not a constant value. So we can just remove that. Cool. Now we also need a build context to where, since this is a stateless widget and yeah, the build context, and then finally the route name we want to transfer it to. So it'll be category deals, screen, or route name. And finally the argument that we want to pass in which can be done using this arguments argument, and then pass in the category as the argument. Now we can take this navigate to category page and pass it in like this, and what do we need to pass in? Well, first of all, context, and then the category to get the category, we can just pass in global variables.So let's get access to them dot category images, add that index where we click and it's tighten pretty straightforward. And here you can see the argument type string can be assigned to the parameter type end. So the error is because we have passed in carousal images, aware it is category images. And now finally year we can put an exclamation mark because it can be now, let's see if we click on any of this, keep shopping for essentials. It shows up, keep shopping for appliances. It shows up. Now the next step is to get the details, which we were working on aware. So now after this container, we need to have another container which will be of the height one 70 and let's make it a sized box. So we'll have a sized box of height, one 70, since you only need to specify the height, no other property has to be changed and the child will be a grid view builder. And just to tell you why we are using grid view builder, again, it's mainly because builder lift view builder grid view builder is always used when we don't know the item count. So I mean, we know the item count, but it's going to be dynamic. It's going to keep changing. So will is good in that because it'll only build on demand, right? So you're, we are going to have constant liver grid delicate with fixed cross access count. And the cross access count is one child aspect ratio is one point so and main access pacing is 10. Great. Now we can have item builder as context index and return something. Now, as of now, item builder is not going to return anything because we don't have access to any of the products. So what we can do is return a text saying hello, and we will specify item count so that it doesn't give us error. Like let's say 10. And obviously we'll specify other properties like scroll direction, which will be access dot horizontal. Then we need some padding. So we will have padding as constant inserts dot only. And from the left 15. So after saving this much, we can see hello, hello. Hello keeps showing up because we've passed in the item, count as 10. And if we keep scrolling, we can see all of them showing up side by side. Sweet. So now let's create an API so that we can get all the data of a certain category so that we can keep displaying them. So you're in the home you're going to create service is, and you are, we are going to have home services dot file. You, we are going to create home services, create a function for that. But before that let's quickly rename it. And then we are going to return a future of lift of products because essentially they're going to be products. And we have, we have seen this pattern already, right? So it's not a big deal. So we just need to do fetch category products, get the build context. So we have build context then, uh, category of which we want to get products. So we have required string category. Now we can create this function and obviously we need a need to write a lot of boiler plate code again. So what I'm going do is go to the admin services and copy all of this code that we have in the fetch all products part, because we need to fetch category products. And it's going to be a very similar thing to that. So obviously let's import all of the stuff again, import HTTP as HTTP dot. Yeah, we have it now obviously make this function asynchronous. You should be familiar with the patent till now, and then import global variables, import HTTP, error handling, and import dot convert. And finally, the utility files show that so that we can show the snag bar. Great. Yeah, everything. Now let's make some changes that we wanna make. Well, first of all, this line is correct. This line is correct. We need all of these. This is for token. This is just for returning the product list. Then your, we need to create our request. So I can go to the product JS file and here we don't have it. So let's quickly go down and in the routes, we will create product JS.And this will basically Fe us all the products of a certain category. So obviously again, we have to write a lot of boiler plate code. So what I'm going to do is go to the admin router, copy this line, paste it away, your then copy this line, paste it away. Your, and then we are going to create a get request so we can take this and paste it in between. Now let's change all of these places. So I'm going to press option on macwas so that I can grab all of these three things and change it side by side. So we have product router and you have, so now we have to pass in slash API. Now this is not, uh, admin route. This is everyone can access a route. So now, and finally we need products. Now, obviously we need a middleware of odd.So let's import that. So we have constant or equal to require slash, and this not this, because this is a route. So we do dot slash middleware slash suite. So now we, first of all, I want to look, I want you to look at this API route that we are creating. This is a get request. We are not doing a post request anymore because we don't want to post any data to our server. We just want to retrieve that data. But along with that, we need to give a certain kind of, you know, body to it. How do we give that body? Well, it's not a post request. So obviously we won't be able to give any body in the get request. So now in the URL itself, we are going to give the body. So how are we going to do that? Well, the Ania URL that we have here is API slash products, but now it'll become, and we want the, uh, from the client side to enter something like category is equal to, let's say essentials. This is the URL that the client side will have to enter so that it can get products off a certain category. You can see that. So with exclamation mark, we are putting a full stop or to our path, which is the main part, which is also the URL scheme of our product router. And then after that, we have the name of our property, which will give us the value of these essentials. Another thing is, if the client side gives us this URL, how are we going to access this value essentials value now to access that we are going to use this request object. Again, we use this for request dot body. We are going to use this for getting this essentials category as well. So to do that, what we are going to use request dot query dot category. So basically request dot query will get us anything with an, with an, with a question mark before it.So suppose you have another URL that is API slash team question mark. So suppose you have another URL, which is slash API slash let's say Amazon. And we put in a question mark, which will be theme equal to doc. That means if we want the Amazon client, if Amazon client side to be of the team, doc, then we can do this. So now to access this dark value, what we can do is request dot query with this, we get access to this dark variable or the dark parameter, whatever you wanna call it, we get access to that. In case you want to have something like API slash products slash sorry, products category is equal to essentials. If you want this kind of URL scheme, then you'll have to use request dot pers dot category. You can see that with this, we get access to this essentials value, but if we use request query, it'll get us this value. When we use question mark, I hope that was clear. Now we can just remove all of these comments and get the particular API product. So what we can do is obviously console dot log it so that I can show it to you. So we have request dot query. We are going to call it category and see if there's much, obviously get the product from the models.dot file. And what do we need to find? Well, a category based on request query category, pretty simple. And then we just need to return that to the user. As simple as it gets. Now, we can take this slash API slash products, go to this. And instead of this URL, we want to pass in slash API slash products. And now we need to pass in the category, which will be category equal to, and then we need to pass in the category, which we have access to through the parameters. So we have category. Yeah, we have it. Now we need to do error handling again. And we will get a product list because we are using find over here in the product route. So it'll catch us a lot of categories so we can just use for loop and all of this explanation and logic. I've done it already. And then finally, we just need to return this product list. Now we can take this home services, go to our category deals and get all of the products that we need. So what we can do is in that state, and we are going to call this fetch category products. We're going to use this fetch category products, call this asynchronous, and this will be list of product. This is pretty similar to what we've already done. So I could have given this as an exercise. Now I think about it, but that's fine. If you had paused the video and done it by yourself, that's a very good initiative by yourself. Try to do it more often throughout this video, because now everything is going to probably be similar except the search functionality and all of that part.I think it's pretty similar. So now let's quickly build the app. We have home service, home service equal to home services, and then we can take this home services and call home services dot fetch category products pass in the required category. So the category is widget dot category because you're getting it through the construction and then we need to call straight so that the entire widget rebels or the build functional, sorry. Now we have access to this fetch category product and the product list. So you're obviously first check in the body that if product list is equal to another, then we need to return a constant loader. Otherwise we need to return a column. Now we can come down and scroll your, so we need to return a column which will have certain children with a size box of height, one 30, then a child of decorated box. And the decorated box will have decoration of box decoration. So now we need a border which will be border dot all and passing the color as colors.black 12, which will be 0.5. I'm not explaining this code away because we have already written so much of UI code that now it should be very familiar what all these properties mean and what will come out the screen. We will see that later on. So now we need to pass in a child in the decorated box, which will be a padding of padding cons, edge, inserts dot all, and pass in a value of 10. Then we need to pass in a child again, which will be image.network. And now we need to get this image network. Now, what is this image network? Well, first of all, let's get clear with the product aware. So product will be product list that we just created at the top. And that particular index that we get aware as we saw builder will return to as an index. So at that particular index, we are going to have this product. Now we have access to that product. So now we will have image.network as product images at zero, because images is our list. So we need to get the very first thing after saving this much. Let's see what we get outputted on the screen. So let's restart our application. And if I click on essentials, yep. Nothing shows up. And that's probably because in our item, count your, I passed in a static value of 10. I have to chain that to product list link, and obviously put an exclamation mark before this product list. Now, if I restart the application and close all of these error messages, go to, let's say mobiles, we cannot get slash API slash products. So that reason is mainly because you have not connected this product, product router to our index Rogers file. So let's quickly connect it. We've forgotten it multiple times. So it's a good reminder for you to not forget and not make mistakes like me. Now, if I click on restart, can restart and go to mobiles. Again. There's nothing over here to see appliances. We have the little MacBook showing up. That's great. Now let's return something else below the size box.So now the very first thing we need to return is again, a container which will be over here in the alignment. So we have alignment.top left, then a padding, which will be cons sets only. And we need to do left zero, top five, write 15. So let's quickly write that. Then we need a child which will just say the product name. So we have text as product.name and then max line is going to be one. And if it exceeds that, then we can just start an overflow saying, text overflow dot SIS, having this much done. Let's see what we are getting. And I'm pretty satisfied with this. Now, if I go to, let's say fashion, there's nothing to see appliances yard, MacBook essentials. We should see a bottle and we see that great. It works exactly as we want it. So now the next thing we need to work on is after fetching these categories, we need to work on this search part.So whenever we search for something, it should show up. For example, if I type S then it should show me stainless steel products on another screen. So let's create the UI and API for that. So here we are in the home screen and here, what we need to do is click on the search bar and whenever the user hits on enter, then we will get some value and then we need to navigate to the search screen. So, first of all, let's close and minimize all the features folder except the home part. And in the features, we will create new feature called search. And this search will have, will obviously a screens folder. And in that folder, we are going to create search screen, do dot. Then we are going to import the material dot, create a state full widget called search screen and call this a constant. And now we will need route name for this. So we will create constant static string, route name equal to slash search screen. Let's say after that, we can take this route name and register it in the router. So let's go quickly over there and register it. So this will be called search screen dot route name. We have imported that and we will get search query that we need to pass in. So again, we need to pass that to the construction because every time we are on the home screen, we enter some value. Then we will transmit that value to other screen. So you are along with that, we will need final strings search query, which will be equal to well, not equal to, we have to generate a constructive based on that. So we have required this dot search query. Also change this to a scaffold so that we don't see a container after that. We can just take in the search query and pass it at the search query. Now you can see the name parameter category is required. So let's see why we need that. And that's because we haven't changed the search screen away. So let's change it quickly. And you, we have it. We have registered the route. Now, whenever the user clicks, we need to navigate to other screens. So here we are gonna create a function called navigate to search screen. We will get a query. So we'll have string query and use navigator use navigator dot, push named and pass in the context. And the route name will be search screen or trout name. Cool. Now let's take this navigate to search screen and find the text form field where we will pass in as the on field submitted this navigate to search screen. So whenever this field is submitted, we will get certain value that we will output it on the screen. So just to test, if it's working till now, what I'm going to do is pass in the body, a centered widget, which will be the widget search query. So if I type hello over here and then click on enter, and we are getting this error because here we haven't passed in the argument. So the argument that we need to pass in is the query. Don't forget to do that. Make sure to add this. Now, if we, again, type in hello and click on enter, you can see hello showing up. If I type something else, let's say, great click on enter.We see great sweet. So now let's work on the search services instead of designing it first, we are going to work on the services part so that we can create our own API first fit those products and then display it on the screen. That would be real farm. So yeah, I'm going to create search services file. And obviously let's remove the capitalized S create a class called search services, and now we need to finish the search product. So what we can do is go to the home services and copy the same thing that we've done earlier. So let's quickly copy all of this because we are going to fetch certain things and it's again, going to be a get request. So yeah, we have that. So let's import all of these stuff that is needed quickly. So we have provider user provider, we have imported, we need provider, let's import HTTP with name spaces. Then we need the global variable. Then we need the error handling. Then we need Jason encode and decode and the shown bar utility. Great. Now we have that. We have copied the same function again, because we are going to fetch the same product. So we are fetch the product. So we are going to have HTTP get request. We just need to change the URL and we need to return the product list again, because we need to display them on the screen, right? That's right. And now, instead of category here, we need the search query. That's the change we need to make. And you name it as fetch searched product, your change, the API. So our API is going to be API slash products slash search, and then dollar search query. Now, if you don't understand this API, that's fine. Now we are going to go there and create it out. But basically what we are doing is slash API so that everyone is accessing slash products so that, you know, that's a convention of our URL. Then we need to search. And then we are passing in the search query. Since this is a get request. If I just show it to you via get request, doesn't allow us to add any body element. That's why we need to pass it in the URL itself. Now, how do we get access to this extra search query that we are passing in? We have already talked about it when we were creating in the, uh, an API in the products dot GSFI. So when we created slash API slash products, you saw, we use rec query category because we are using question mark you. But when I, I told you that whenever we use something like this suppose search, then we are going to use requests, category, or requests, whatever is the name, or just request paras.You get the idea. So that's what we are going to use. Let me remove this console log it's not needed. And also this URL. It was just to demonstrate it to you. And now I would've given to you given this to you as an exercise, or you can actually do it as an exercise to create an API, create a get request to search products and get them well pretty state forward. But this is going to be a bit different. If you want to try it out, Google it out and use it and find the correct solution. You're free to do it. But if you want, we can go along. This is a bit different from what we've done in the past. So obviously we are going to copy all of this and call this slash API slash products. But after that, we want slash search. If we go to the search services, you can see we have slash search and then the search query. Now we want to get access to the search query. So what we will do is slash search and the name with this, we can get access to the name. So just putting a colon over here, we get access to it. Now, if we pass something over and suppose we get a request to the URL that we have already passed in the client side. So we have slash API slash products slash search slash let's say, I wanna find an iPhone. So I pass an I. So we want to get the access to this. I to get access to this, I, now I can simply use request paras.name because you've named it as name. Now, if I type in over, let's say hello now to access this part, we can ask dot hello. If I have another per, after this, let's say, great. I can access this great using request.You can see, this is how easy it is, even if it's all hello. And it gives us the autocorrect option. That means we are doing it everything correctly. So now having that idea, what we are going to do as to remove this and make it an readable format. And now what are we to find? Well, obviously this part is going to change. We are going to save it in products and we are going to innovate, use product dot fine, but the condition is going to be bit different. Remember when we use rejection, our application, we are going to use rejects. Now earlier we used reject so that we could validate our email. And we found out that REDX is used to, is used in search patterns. So exactly what we want to wear. We need to use search patterns so that we can get that. Now mongoose and MongoDB have built in support for that. So what we can do is pass in the name because you want to provide products by their name and then pass in the rejects. So we have dollar rejects and then pass in request.paras.name, <affirmative> name, and then options.I, with this, we are able to find the products based on their name, even if the name is iPhone and we find out and we type in, I, it will features this product, which is pretty cool. And then we just send in this product, nothing else after creating this API, which was very simple. And actually, before going there, an alternate of approach you could have taken is finding the product based on this name itself. So we just pass in name as request dot paras name. Now this would've worked. If you passed an iPhone, if your product name was iPhone and you passed an iPhone, then only the product would show up, but it wouldn't be a search pattern to get search patterns and some products with similar names. We have to use the part of RegX part. Great. Now we can go to the search services, pass in the URL that we have correctly. We need all of this. Again, I've explained it to you earlier. You must type it out so that you get a hang of it. And if you have a better approach, make sure to cry that approach first and then use it in your application. If you find that as a bit of a, and then you're going to return the product list. Now let's go to the search screen, use the init state function, and we've done that loads of time. So we are going to do it again. So we have list of product called products. Now we can take this product and set it equal to, well, first of all, we need to get, create a new function. So we have fetch searched to product. Then we need the switch search product function created. And now we will have products equal to and well, final search services, search services, equal to search services. We can take this, pass it in and fit the search product pass in the context and the search query widget, which is widget dot search query because we are receiving it through the construction and ADE. This now, obviously we need to set state because we changed the value of products. And now here we can check. If products is equal, equal to Nu, then we need to return a constant loader. You might be familiar with this pattern already by now. It's just a practice of writing it again and again. So you're used to it and you get confident to build any other application that you want. So now if we restart it, let's see what we get. You are basically let's type in high. So yeah, let's type in high and you can see high is showing up, but we are not printed any products and it's not giving us any error again, your as well, that means it is a success. So now let's build the UI of this app. So here we have the UI of the app that we need to create. Well, first of all, is the same app bar. So let's quickly create this app bar at the top right now. So we can go to the home screen, copy this app bar, paste it in the search screen. After that import everything, we need to create this function, but we can import this and now go to the home screen again, just to import that function, not import actually create that function. And now past it over here there, we have it. Great. Now, if you come aware, looks right now, the next thing we need to work on is first minimize this so that it looks less gigantic.And in the body we are gonna have column and in the children, we are going to display, first of all, the address box. So we have already created a widget for that, which is called address box. Let's have that Great. Also remove the loader from here and paste it in the body, put a space AOR. Yep. Otherwise, you know, the scaffold won't be there and it would be an ugly bar that is showing up continuously, which is not what we want after that. We need a sized box. So we have constant sized box of high 10. Then we need an expanded widget so that it can take whatever spaces available because the rest of the space is all for our search products. And we need to display a list view builder so that unless view builder will give us an error. If we don't specify some height and what height do we want? Well, all the available height for us. So we can quickly wrap it with an expander widget. After that list, view builder, we'll get a context and an index, and then we need to return a product or a widget that we will call search products and create it manually. But we also need to specify item count for that. And our item count is products link here. We earned to return the search product. So let's create a widget for that. In the widget, we will have searchedProduct dot. We will import material dot, create a stateless widget, call it searched product. Then we will receive the product from the parameter so that we can display their details successfully in the product. After that, we are going to return a column because if you see, let's break it down. So if I break it down really quick for you, we have a column widget inside of which we have A row. And in that row, first of all, we have this image. And after that, we have, again, a column with that column. We have a text that is showing this a rating widget for which we are going to use a package, then a text again, just to show the price and then eligible for free shipping and in stock that is there. So now we are going to return a column, the children, and the first child is going to be a container with some margin, because you can see there's some margin from the top, from the left and the right side for the top. We use size box, but we need it from the left and the right side. So we are gonna have a container so that we can pass in certain margin. Then we need constant edge inserts, dots, symmetric. And in the horizontal direction, we need 10 because they're both left. And right, if you're wondering why I'm always using horizontal, if you click over here and come away, you can see horizon horizontal is for the value of left and right, both vertical is for top and bottom instead of specifying dot only and write 10 left 10, what you can do as horizontal 10, after that, we need a child and the child is going to be wrote as I talk, we need an image and the description of the product later on. So we have image.network. And you're the first image that we're going to show is product dot images at zero. If you want, you can create a carousal, but it would be really laggy and wouldn't make app look, feel really good. You know, so here we will, app fit as box fit, dot, hide, fit height, and let's see why we're getting this error. And that's mainly because here we pass in the children for the row. So let's pass it in, take this image.network, past it in. And well, the height should be 1 35, which should be 1 35. Now let's go over here just to return the search product and see what result we are getting till now, and then pass in the product for us. The product is going to be product products at index, and there we have it because this is a list and we're accessing a particular product using their index. Now we save this much and restart the app, open up the DVA console and the, and let me just to remember the products that we are. So we have stainless steel product. So I'm going to type in big S because it's in small S so I'll just type in this and you can see stainless steel pops up amazing. Now, after that, we need to display the products of the, uh, sorry, the description of this. So we will have, again, a column with children. And the very first thing we're going to have is a container of with 2 35, then padding of constant agent sets dot symmetric in the horizontal direction, 10, then a child just displaying the products name. So we have product name, passing the style as constant textile of phone size 16. And now if it see the stainless steel pops up, it'll go up as, and when we get new products, but also let's add max lines as two after which it'll just cut it down so that it doesn't exceed. You can see that, then we need another container. So let's copy this, paste it down. We need a container of it, 2 35, but the padding year will change. The padding will become from the left. We are going to have 10, sorry, left then. And from the top, we are going to have five and changes to only. Then the child is going to be The stars because you are the next stars for stars. You're going to create a separate reusable widget over your, in common. So we have stars dot dart. Let's import the material dart create a stateless widget for stars and your, we are going to make use of an external package. So the package we'll be using is this fluter rating bar. We can copy that, paste it down your, and you can see it supports on all the platforms. So as soon as Google pay apple pay, start supporting Android iOS. It does support that, but Linux macro, web, and windows, we can start deploying it everywhere because none of the other packages need any other thing. So obviously we are going to get the rating from you. And for now, we are, as long as you're not working on the rating section, we're going to tell that the rating is going to be a static value just after we create the rating. We are going to change those ratings. So you're in the terminal. We are going to pass in rating bar indicator, and we are using rating bar indicator because it is only a view, view, only visit. And you want the direction to be access horizontal. After that, the item count is going to be five and the rating is going to be the rating that we get from the construction item, count specifies. How many stars do we wanna see? And rating will tell us how many stars should be filled. Then we specify a fixed item size, which will be 15, then an item builder, which will give us context. And other thing that we know don't need, and we will just have to display an I icon. What is I icon that we want to display? Well, I icons.star and the color should be global variables Dot secondary color, because that's the golden color that we need. Now we can take the stars, paste it in instead of the product's name and pass in the rating for now, it's gonna be a static value. So just to see if it's working or not, we are going to have four and mark this as constant, save it here. We have it. Four stars are filled and it looks great. Next thing again is going to be a container. So let's quickly copy this, paste it down. And what do we need to show? Well, the price. So let's quickly have a width of 2 35 again, but the, we, again, we are going to have the same pattern as the rating. One, we can copy that and paste it away, and the text is going differ. So yeah, we are going to use string interpolation because we want to use a dollar sign. And as we saw for dollar sign, we're going to have dollar dollar product price. Max line is set to two and phone size should be 20. If we save this dollar 10 shows up, let's just bold it. So we have font, weight, font, weight, And now it's bolded looks sick. After that, we can just copy this container just to write free shipping and in stock. So we can have two of the same thing. And we want your only left as 10. And we'll just say a text with nothing as a styling and say, eligible for free shipping. And we can have a constant after that we will have in stock. So we will have in stock. Max lines will be two, and the color is going to be colors dot peel. Let's quickly write that out and remove the constant from everywhere. Press on command, full stop, and add a constant modifier. Instead of passing it over here, we need to pass it over here. Great. Now we can see it's looking similar to this and it looks great exactly the way we want it to look. So now, just to check if it's working or not, I'll write Mac and click on enter. You can see MacBook air M one showing up. And if this photo looks ugly to you, what you can do is change it. So in image.network, we will have fit with. And if we save this much, this whole picture comes in. Now, the next thing we need to work on is whenever we click on any of the products, we want to see their details all. So your is a design of the product detail screen that we need to create. So what we need to do is minimize, let's say some of the folders and in the features folder create a new folder called product details, and then click on the again, folder sign so that we can create screens folder and then create the product details, screen.dot file. So here we are going to import material dot, create a state, fold widget, and call this product details. Screen, obviously add a cons to conveyor, and now we want return A scaffold with an app bar, right? If you come back to the way you can see, this is a bar that we need to create. So to create that app bar, we will go to the home screen, copy this method, paste it over here, then import search screen. After that, we can again, go to this home screen. So we just need to copy this app bar, copy this and paste it in the product detail screen. So let's come over here and paste it down there. After that, we will need global variables import, and we have already passed in the function aware great. Now to test this application, uh, test the screen till now we can have a static, constant string route name, which will be slash product detail screen. So we can just name it like this. And obviously we need a product so that we can display its details, and we will require this to the construction. So let's click on generate construction and here we have it. Now let's register this in the router.dot file. So copy this, paste it down here. We will have product detail, screen, route name, then call this product detail screen pass in the product. And the product will be saved from the argument so that you are it as product. And we will treat this as a product and now just pass in product away. And our router is set as well. Now we can close all the safe files, go to the product detail screen, because that's what we need to style. And in your, after this app bar, we need to work on the body section. So let's see what we need. Well, first of all, we need the ratings part and the idea of the product. So let's quickly create that. So you will have a single child scroll view because you can see different screen sizes. And as I mentioned before, different screen sizes will lead this to scroll. And if there's too much of description, if added for any product, we want it to be scrollable. So after having that, we can create a child which will be a column. And then in the more column we need children and the first child we are going to have your, is this row. So let's create this row. It's children will be text saying the product's ID. So we will have widget product ID so we can see that it can be Nu. So yeah, we have it. ID can never be Nu after that, we can have star widget, which will be reused and the rating will be well for now static. So we can just pass in forward. After we calculate and add the rating part, we can change this to something real. After that, we need to add the main access alignment, uh, main access alignment space between and save this much also to see whatever result we need. We can just use broader product detail, screen dot route name. So where do we want it? Exactly? Well, whenever we click on this category and click on this product, so we need to go to the category deal screen. And whenever we return a certain product here, we need to wrap it with a widget call, gesture detector, and we'll pass in the on tap, which will be just navigator dot push name. And then we need to pass in the route name, which will be product details, screen, route name, and then finally not to forget arguments, which will be the product after that. Let's save this much and here we come. So if you click away here we are. We're seeing the correct things. Now we want a little bit of padding from the side. So what we can do is go to the products layer and in the row, we are going to add a padding. So wrap to the padding of <inaudible> dot all eight. Now this looks better after this. The next thing is the title. So let's have a padding widget again, so that we can leave space from the side and the top. So we will have padding constant edge insert dot from the vertical side, we want 20. And from the horizontal side, we need 10. After end, after that, we need a child in it, and the child is going to show the widgets product name. So you'll have widget product name and let's configure the size for it. So it will be constant. Textile font size will be, let's say 15. After saving this much, you can see stainless steel. What is showing now in case you wanted to start from here? What we can do is in the column, pass in cross access alignment as cross access, alignment dot start. Now we can come aware and you can see it's showing up pretty cool. After that, we need the image and this image is not just one image. It's going to be a carousal of images. So what we can do is after this padding, again, create a carousal slider. And for that, we have already created a widget. So let's just copy this, paste it away. Is it aware and import carousal, slider aware the item is widget dot product dot images that we need to map through. And every image will give us I, and all of that is fine. Now let's remove this current thesis and port comma and your VRIT looks great, just that the image size isn't matching. So we can change this height to 300, not this height, let's say the height away. We can change it to 300. And yeah, this looks bigger and cleaner. After that, you can see, we need a bit of divider or spacing for that. We are going use something cool. We are just going to use a container, but in that we are gonna pass in the color property of colors.black twelves with that, we get this kind of layout, but you can't see it. So let's increase its height. So that will be five. And after doing that much, you can see this great divider exactly like Amazon showing up after that, we need to show this price.So after the container, this is a deal price. Now observe the differences in the text here. You will see that the deal price is a small text, and this is a bigger text in different color. And as you've already seen, we can use raw widget for it. Otherwise we can use rich text and text span. That's exactly what we are going to do. So obviously have a padding so that it doesn't mix up all. And you'll have insert dot all eight after which we will have a child of text span, rich text, sorry, that will take in a text. And the text is going to be a text span. And in that text span, we're going to enter the deal price. So we'll have deal price. And also it is a name document. So we need to pass in text via, also put a trail income. After that, we need to specify some style, which will be constant textile. And the font size will be 16. Color will be colors.black. Even if you don't mention it will be black, but since we are having a difference of colors in the next text span, let's mention it. And then finally we have font weight, which will be font, weight. Let's put some comas and also put, uh, spacing over so that in the next children child that we have, there will be a letter of space. Great. Now it looks good. Now we just need, uh, price. So for price, we can pass in, in the rich text, in the text span, sorry, children. And the first child is gonna be a text span. So let's just copy this text span, paste it in over a year and we need another parent thesis. And here we need to display the price. So obviously we are going to have dollar which will be back slash dollar and then dollar widget product price. Now all of our warnings faded away because this child, one of the children has a text, which is dependent on a state variable. So to say, since you're, depending on the structor, it can be a constant value because it, it can change time. It will not be constant. Now, if you come aware, we can see no difference in the text, font size or anything. So let's make it 22 and change this to colors, rot red. Now, if we save this much, this still looks, you know, this flashes in the eyes, the red color. So we can change this to font, weight w 500 after that, this looks great. Now the next thing is leaving some space. We want the description. So let's copy this much. After the rich text, we are again going have PAing, but we will add that later on. So we have widget product dot description, and also let's put it after the PAing widget and then see this stainless steel. Great. Now we will just wrap it with a pairing visit because we want all cons agencies dot all eight after saving this much, you can see this looks neat, but when we have a bigger description, this all will make sense.After that, after that, you will see that we need a kind of, again, this container, so we can just copy it, paste it down here, and then we need the buttons. So we need a buy now button and add to card button. So obviously we are gonna have custom button text will be by now And on tap will be empty function or an anonymous function for now, after that, we can just see what we are getting this isn't looking really good. So what we can add is a padding widget again, and in that pattern, which we are going to have constant edge and search dots symmetric from the vertical direction, 10 and from the horizontal direction also 10. So what we can have is 10 overall, instead of vertical 10 horizontal 10. I didn't realize that while writing the code myself, but now we have it. Great. Now we can just copy this again and paste it down after a sized box of 10 so that it, they both don't stick together. And now this will change to add to card.Now, if you come back, you can see the color change, oh, sorry. The product two buttons showing up, but now we need to change the color for that. We can go to the custom button and here, here, we will accept a few arguments. So we'll have final color color, and this is only needed for product. It is page. So we can have this draw color with not required and no default value. This is not needed because here we are going to pass in the style, the primary color, which can be Nu you can hover over this and see, this can be Nu. So this can also be null. And if we don't specify anything, primary color will be null and will default to the main theme of our application, which is this orange color. Now, if you go to this, add to card and pass in the color, and the color is going to be constant color from RGBO 2 54, 2 1 6 19 and one. And if we save this much, you can see the difference, but now we need to change this color as well. So now to change the custom buttons color inside of the text, what we can have is a style And the style will be a textile where the, where the color will be a conditional operator. So we will check here. If color is null, that means that the user does not enter anything. Then we want it to be white because here we never mentioned anything, right? That's why the color was white aware, but in case we mention it, we want it to be colors.black, simple enough. And now we get the black color. Great. After this padding widget, we can have a size box again of the high 10, and after that a container. So let's quickly copy that and save this much. Yeah, we have it now. Final thing, if we see the rate product, so the rate, the product is going be fairly simple. We're going to have a pattern of text. So let's quickly just copy one of the text. Let's copy this one, paste it down. Your, so the engine sets will be symmetric. And from the horizontal direction we need 10. Then in the child, the text is going to be read the product. Then we can have some styles passed in. So we'll have style constant textile, and let's remove constant from everywhere and put it in the paring widget because we know everything is static over. So the textile is gonna be font size 22, and font weight will be font, weight dot bold. After saving this much, we operate the product scene. Now, finally, we want the rating bar that we have created at the top as well. But now we can't use the same widget because as I said, it was view only. Now we want to make changes. Whenever we tap on it, we want to rate the product. So for that purpose, we are going to create rating bar dot builder, which is another widget provided by the same package, aim package, flatter rating bar. So if we come back over here, you will see in the item builder, we get context and an index, but we don't need the index for now. And we just need to return a constant I icon of ikes.star with are with color as global variable, secondary color, after saving this much, we need on rating updates. So whenever the rating updates, what do we need to do? Well, it has returned to us some rating that the user clicked and on, then what do we need to do? So we will configure this in just a while after creating this UI, and then let's see what we get. Yeah, we have it. So if we save this much, you can see, we can rate it anywhere, but there's still a bit of, you know, configurations I want to do. So, first of all, I want to add an initial rating. An initial rating will be dependent on the average ratings that we've received so far. So in case 10 users have passed the value for the rating. And then each one has passed in suppose 5, 4, 3, 4, 3, something like that. We need to take average of them and show it as an initial rating so that the user can rate that much as a rating. Then the minimum rating that the user can give is one. We don't want the user to get zero. Then the direction will be direction, access dot horizontal, and we will allow half a day. So after that, the user will be able to give half values as well. So if I click away, you can see half values given. Great, so that the double value that we've stored in our Mongos comes into use. And finally, we know item count, which is fives and item pad, so that this doesn't look so much congested. So we will have constant engine search symmetric from the horizontal direction, passing four and great. We have a rating that created now, this looks great. All right. So now having that, that you, I created let's bind it to the search product as well. So if we search suppose MacBook and click on enter, and if you click over, we should be able to go there. This is fairly straightforward. What we can do is go to the searched product, sorry, searched screen. And whenever we return the search product, we want to wrap it with a widget call as gesture detector. And again, on, on tap, we want to navigate. So we have navigator dot push name, pass in the route name, which will be product detail, screen Dot route name, and then pass in the arguments, which will be a product. Now the product is the product list that we have, where you can see that and that particular index. So we can just copy this and pass it as the argument. And it won't give us any errors. Now, if I click on this, you can see we are seeing the product, but still the image looks very bad. So what we can do is go to the product detail screen and in your, in the image.network part, we can have fit dot contain. And now we have, it looks great, exactly what we want. So now let's work on the rate product functionality. All right, so now let's create a new folder in product details called services, and this will be called product details, services.dot file. And this will obviously we have product details services. So the very first function that we're going to have is the rate product function. So let's create that quickly for your rate product. This will be taking in a build context actually, instead of writing all of that again and again, I would recommend you to do that, but I'm just tired of writing it again and again. So what I'm going to do is go in one of the services and extract it. So I'll just paste it over ya. After that name, this to rate product. And I require bill context, I'll take that. Then I require the, all of this is not required. Even this now what's required is the product that I want to rate. So let's take that so that we get the product's ID, which we can take in the server side. And then obviously required is the rating that the user given after that we need the token of the user. So we need provider after that, all this Cloudinary stuff is not needed, even the product thing. And then we need to import http@http.dot. So we have that line and then we need global variables. And after that, the utility files and even this GTP error handling part. Great. So now let's save this much. So your first of all is gonna be a post request. That's correct, because you're gonna send body data to it. So we have the headers also there, and the body that we're going to send is, well, first of all, Jason encoded, don't forget to do that. Then we need to pass in an ID, which will be product ID and then the rating. So let's pass in the rating and great. We have that And also change the API over. So we have slash API slash rate product. Now saving this much. We are good to go. Now, also remove all of this. We don't need any of this in the own success. Now let's create an API for rating the product. So we'll go to the products model. First of all, and here we have the comment of ratings. So we need to change that model. We will create the ratings property, and this ratings is going to be an a right, many users can pass in and it'll be an a of object. We have never used this part before. So let me just create one. So we elaborating JS This rating JS is going to contain the structure of this rating that we are going have. So we are going to have constant Mongo equal to require Mongo. And then we are going to create the rating schema and we'll have Mongo schema. And yeah, we are gonna pass in the user ID, the person who rated this. So what is their user ID so that they can't, you know, change the rating again, if they do change, we are going to add the logic to remove the previous rating and add the current rating. And then we are going to add this as a type of string and going to require it as true. And if you're wondering why this is not a type of object ID, which is a thing where, so something like this, the object ID that's because we are getting the token from the client side and that token is going to be a string.Sorry, the ID is going to be a string away, which is understood. Now we need a rating, which is going to be a number. So we have type number and required set to two. Now we are not going to make a model out of this. That, that is a key thing to note. Whenever we just want to provide a structure, we don't need to provide it with, uh, model. If we provide a model, it'll create an entirely new model in our fight, and also add that in the product model, the rating schema. And it'll also give us the underscore ID and underscore underscore version part, which we don't need, right? So we will just use module dot exports, equal to rating schema. Now we can come over here and pass in the rating schema as the object. So this ratings is going to be an area of all the rating schemes that we're going to have. And it'll be like an object which will contain multiple objects of various users. Now we can come to the product GS route and create a route for that. I give you the exercise of creating a post request route to read the product with this, with the knowledge we have. I think it's pretty easy for you to go ahead and use that to read the product. And if you get stuck anywhere, like you want to delete the products like you want to delete an object from the products, a I would recommend you to search it up on web, on how to delete an object from an a in Java script. Googling is a part of this task. So I hope you can do it. Were you able to do it? If you were, then you're all set with no J that's my guarantee to you. So now we have product routed.post/api/rate product. Then we need to have authentication. Then we are going have asynchronous request response, and then this created then a try and a catch block. Then we need to return a rest dot status of 500 Jason and send in the error message in case there is any error Now in the tri block, first of all, we need to extract the ID and the rating from the user. So we are ID rating equal to the request dot body because we sent it from your, the body part. After that, we are going to find the product because we need to make changes in that product's properties. So let's quickly find that product. So we will not make it a constant because we need to change the properties and, uh, product equal to product, find by ID. And we will find that ID, and we're not using find by ID and delete because that will delete the entire product. We don't want to delete the entire product. We just want to add or remove a rating. And why do we want to remove a rating? We will see that logic now. So first of all, what we need to do is run a for loop on all the ratings that the product has. So in case the product has something like this, let's quickly try it out. So your is the user ID And your is the rating. Let's say 2.5. And then we have, again this past in, so let's quickly add that. And your, the user ID is a bit different and the rating is full. Now this is all, uh, part of the ratings add on the product property. So this objects can be accessed using product dot ratings. Right now, what we need to do is loop through each one of them, checking if the user ID is matching with the ID that we have passed in, which is this user ID. So the user ID from request dot body, if that is equal to this user ID, that means we've already rated that product. So that means we need to remove that products ratings, correct, pretty simple to law. So let's quickly create that we have four led. I equal to zero. I is less than product.ratings.link. And then I plus plus, the reason we're able to use length on this is pretty similar to dot. We have product dot ratings, which is an a, now we can access all the properties that are there on a like length includes all of that stuff. And then we are looping through here. We are checking if product dot ratings at I. So that means product properties, ratings at I. So we will get access to one rating. And this rating doesn't mean this rating. This rating means the entire object aware if that ratings user ID, which gives us access to this. For example, when we are on zero, when we are on one, it'll give access to this, if that is equal to request dot user ID. So yeah, we are checking if product dot ratings at I dot user ID, which is this if equal to request dot user, which is the user's ID, this is not user's ID. It was my bad, it was the product ID, but here we get access to user's ID using request user because of the middleware. So if that both is equal, what we are going to do is product dot ratings do splice I one. Now splice is a new feature or, you know, a different feature from dot. This is available on basically it'll allow us to add or delete anything If we have access to the index. So if we just remove this again and I'll show you, you can see, we need to pass in the start number and the delete count so that we can delete it off. And we can even add products using splice, but I'm not going to show it here. You can Google it out, but with this, you're basically deleting the product because we have access to their index. So here we will start the number. So from what number do we need to start deleting? So person I, and how many numbers should we delete? Or how many objects do we delete? Well, we are going to delete only one object because we need only one object to be deleted. And after that is deleted, we can just break it because we are not running it for an extra loop and wasting our time after that, if there is any extra rating, it'll get removed, and then we are going to add that rating schema.So we're gonna have rating schema equal to first of all, the user ID and strings are not needed like this in JavaScript. So we have user ID as request dot user and rating as the rating. So we can have a short time syntax for that, which is this. We have access to this. Now we can use product dot ratings dot push. And as I told, we have access to all of the methods. Push is like add in Java script. So we are going to use push and it'll push to the end of the I a new element. And what is that element? The rating schema, because that's exactly what ratings needs after that. We will use product is equal to elevate product.save, and we will address Jason as product. And now we will remove all the ratings and save this much. Now we will copy this, make sure it's the same over here. Great. Now we are rating the product part, and now we want to bind this function to rate products. So what we can do is in the product details screen, we can go there initialize it. So we have final product detail screen called product detail, screen equal to product details, screen, uh, sorry, we don't need product details. Screen. We need product details, services, product details, services, equal to product details, services, else services. And then we're going to have final and also push this function down. Great. Now we have access to this product detailed services. So we can go down in the on rating update where I told you we are going to make some changes here. We can pass in product detailed services dot rate product pass in the required context, which we get from bill context. Then the product, which is widget dot product, getting it from the constructor and the rating. This rating is from on rating update. It'll give us the correct value of which we click click. So if we click away, it'll give us five. If we click on half the part, it'll give us 4.5 great value. So now if we save this much and we've not added anything in, on saved on success, we will open up our diva console and a terminal to see there's an error. Nope. We can go to the essentials by a stainless steel. We will give it a five and see if there's any error, nothing at all. So now if we come back, go in the appliances again, not appliances, sorry, essentials, stainless steel. We can't see anything because you're not showing anything, but in case we show it. So just to see if it is success or not, we can just go in our products, more collection in our collections and here passing the ratings. So here we have the ratings as rating as five and the user already given now, in case I change it again to let's say 1.5. Let's see if we have that. So if I just go there and refresh the app, your let's see the, your, we have it 1.5 and it has removed the earlier rating that we had, which was five because of the logic that we created over here in the product. GS file this logic. Great. Now let's just see the ratings on the screen. So whenever we come over here, we should be able to see the correct rating. So for that, what we need to do is first of all, go to this product dot model. And in this model's folder, we are going to create a new model called rating GS, and actually not rating GS, sorry, rating.dot. And here we are going have class rating. We will initialize the properties of string, user ID and double rating. So we have final double rating. After that, we will generate a constructive for them generate Jason serialization. And we are that done. Now we can come over here in the product that file and pass in a property called final list of rating, which can be Nu called rating. Now we need to pass this in. So we have, this is not required. So we have final this.id. So this not this.id, but this dot rating, after that, we can come away, pass in the rating as rating and near the rating will be a bit different. So here we will first check if map ratings and make sure to name it as ratings because in your Jason app or your product JS model, you've named this as ratings. So make sure to make that change. So map ratings, if it is not equal to Nu, then we will do something. Otherwise we will return null because it can be null.Then we are gonna check a list of rating dot from map at ratings. We are going to check if that's knowable, if it is knowable, then also we need to map over this so we will get access to X and then we will convert it to adjacent model called rating dot from map and pass in the X value, not the map. And yeah, we have it. This is the logic that we need to create. So let's put some coms. Yeah, great. So we have the rating model created. Now we just need to display that rating. So you are at the top. We are gonna create an innate state function in that innate state. Well, first of all, we need global variables of double average rating, which will be said to zero initially, and an variable for my rating. So average rating is going to show up over a year because that is average rating. And my rating consists of the rating that is to be shown near. So now double, total rating is going to be in the innate state function because total rating is not needed anywhere globally. So it's good to have a member function away and now we are going to run it. So we have four equal to zero. I is less than widget dot product dot rating Link. And we can, this can't be question mark. It has, could be exclamation mark. And then we have I plus plus, so here what we do is total rating plus equals widget product rating. I rating, and here there has to be this here we are basically calculating the total rating that the product has ever got. We can't calculate the average array because first we need the sum and then only we can move forward with calculating the average rating. But even over here, we need to check first if widget dot product dot rating At I dot user ID is equal to provider dot and let's have provider dot user provider context, listen, set to false.user.id. So if both of them match the user ID in the rating and over year, then we need to make sure that we change my rating. So we have my rating equal to widget product dot rating. Actually let's copy this one. Pretty simple logic. Don't get scared by the complexity of code that is senior, but just the logic is pretty simple. Nothing else you're doing. And you're outside of this follow loop in this fall loop, we are putting enough condition so that we don't have to run another follow loop running from I zero to like this. I plus, plus just to get the user, we can do that over year as well. And now we are just checking. If total rating is not equal to zero, then average rating, which we created as a global variable is equal to total rating divided by vision.product.rating.link.Basically, we are checking if total rating is not equal to zero. So if total rate rating is equal to zero and we perform this operation, it'll give us an error of any end, which means it is not a number. If it is not a number, then we cannot divide it by anything in that. So we thing and not. So we are checking over here. If it is not equal to zero, then average rating will be equal to the total rating, which is the sum of all the ratings that we com computed over here divided by the length of the ratings a that we created. Now we can just take this average rating and total rating and pass it down. So you are in the stars. You're going to have average rating and remove this constant. It's not a constant anymore. Let's see. We are not seeing anything. And now if we go down to the rating bar builder, you are, the initial rating is going to be my rating that the user has already filled it. And the minimum rating can be one. And all of that is still valid. Now, if I restart the application and see what we are getting till now, I'll go to the essential stainless tee and you can see 1.5 stars over year. And even over year, if I make it five, go back, come back over year. You can see five stars given. That means the rating part is working really well. Now we just need to add the rating part in the search. So yeah, if I type MacBook, you can see four stars is a constant that shows up now, instead of doing that and just to show you, even if we do it for stainless steel here, we have four stars showing in fact it should be five stars. So what we can do is go to the product, sorry, search screen, and searched product, where we are using stars somewhere. We can go there and in the rating, but what is the rating going to be like? So for this, we are going to go over here in our be function and create the same logic that we did in the detail screen. But instead of the, in it state function, we are going to do it over here. So let's just copy all of this, Paste it in. And we don't need this. If logic again here. And we also need to remove all of this product part widget dot product, sorry, because this is not a state full widget. This is a stateless widget. And that is the reason why we are doing this in the build function. That screen was already in a stateful widget. So we could use in it state. Now, instead of creating it as a stateful widget, we can just compute it over here because anyways, no, no set state is happening over here. This does the job of only displaying it. So the widget rebuild is not going to happen ever again. So build function is a safe place to do it, at least in this case. So here we are going to create a variable called double average rating and set it equal to zero. If you do it over a year, then you'll have to remove a constant. And then we don't get any benefit of using a stateless budget instead of a function. After using this, we can take this average rating and pass it to our stars. Now say this much and your VC five stars. Now, again, over your, if you had a problem with this image, obviously you can change it to contain and it'll contain the entire image and this will look good. Great. So we have the ratings part completed. The next part is the add to card feature. Whenever we click on this, add to card, it'll add to our card and then we need to make a UI for that as well. All right. So to get the deal of the day, what we are going to do is go to the product GS route. And in here, you're going to create a ghetto for deal of the day. If you want, you take it as an exercise to do it on your own and scratch your brains until you do it, it'll be really great. But just to mention deal of the day is going to depend on the rating. So whichever product gets the highest rating is going to be the deal of the day. Pretty simple. So I'm gonna call this API deal of the day then off as the middleware and then request responses this, and then a try catch block just to display any error if we get any. So I'm just gonna have this past in Great. Now in the tribe block, we are going have first fetch all the products. So we are gonna get, let products is equal to innovate product dot find, and this should be equal to sign, not minus and also pass the semi. So yeah, we are just getting all the products. Now, what we are going to do is what the logic is that we are going to sort all of these products based on their ratings. So we are going to take each product's ratings, match them against their own, and then check whoever and then sort them in our defending order so that we get the very first element as the best element. So suppose there are product a and then there's product B. So product a has a total rating of 10. First of all, we need to calculate all the ratings of the product. A and if the product B has a total rating of let's say 30, so, and let's say we also have C, so C has 50.So it'll check the total. It'll first calculate the total points of B and C together. And then it is going to check if 10 is greater than 30, if it's greater than 30, then it'll just sort it out in a defending order. So that C comes on the top. B is the second and a is the third. Now to get the deal of the day, we have a sorted products, a we can just access the very first element since it's in descending order and has the highest number of points. Great, pretty easy. So what we are going to use for this is products dot sort, which is a method provided by JavaScript. It just sorts a value, and it'll sort the value based on what we output, but here we will get a and B, which are two numbers. Now, if you think there will be any confusion from your side, you can just name it.Something like product one, product two, but I'm just going to go forward with a and B. And here we are gonna create a function based on which it is going to sort itself. So first of all, we will create a temporary variable called Ania, and don't worry, this sorting is basically, it'll go through all the products and then sort one against each other. It'll done some sorting algorithm inside of it, which we don't need to worry about. So here we have B sum zero. So even if products are more than two, don't worry this a and B just symbolize product one, product two, which keep on changing every time. So now what I'm going to do is calculate the ASEM for that. We are going to use for loop. So Follet I is equal to zero. I is less than products dot, sorry, not products, but a dot ratings dot length.So ratings is the model property that we created on product. And then we are going to increment by one. And then we are, what we are going to do is a sum plus equals so that whatever pre value that we have is added plus a dot ratings at I. So we get the particular object, which now consists of the rating as the number and the user's ID. So now we will do rating and that's it. We have a sum ready. Now, similarly, we have to do the same thing for B sum so we can pass it in over here. And we have B do ratings, rotting, and B sum plus equals B do ratings at, I do rating. We can't do both of them in a single follow loop because this will run till a do ratings rotting. And this will B do ratings, struggling. Both can defer After that. We just need to return a condition. So based on which it can sort, or we have not yet provided the condition on which it should sort. So here we are just returning that asso should be smaller than BSO. So if asso is smaller than BSO, then we want to return one. Otherwise we want to return negative one. Why are we returning this? If you over over this, you can see sorts and a in place, this mutates, the a and returns a reference to the same, a that means we're going to get an a, so what we are going to do here is products equal to this. So it'll just mutate the a so that we can get the reference to the same. A, that means it'll give us the same, a sorted, but here, what does this mean? So again, we hover over this and scroll along. You can see function used to determine the order of the elements. It is expected to return on negative value. If the first argument is less than the second argument, zero, if they're equal and a positive value otherwise. So here we could have done a, some minus B sum and removed all of that, but I like to do it this way. It is like a convention for me. So here, I'm just checking. If Ania is less than B sum, that means that B takes precedence over ASO B some will be Pushed at the top. And negative one means the opposite. That is a takes precedence over B. And thus it is arranged in a descending orderAfter having that area and storing it to products. What we need to do is just return that, and we don't want to return the area of the products we want to return. The only one product. And that one product is going to be the top most element since it's in descending order. So we have products at zero and there we have it. We created the API. Now you can test it and send the client, but now you might be used to it. I'm not doing that. It's very good for you. If you do it after that, we can go to the home component. Let's minimize search product deals and admin in the home part. We have deal of the day and home services. So first of all, let's create an API and home services. So I'm going to copy this, paste it in Nova. And we are going to return just a single product, which will be a future. So let me just have product return. And this will be named fetch deal of day. We are going to require nothing else, but the build context, so that, you know, we can show snack bars and use provider. Now we have product list. Instead of that, we just need a product which will be product Product equal to, and now we need to instantiate this. So that later on, I'll tell you why we need to instantiate this. And we are not putting this as Nu, but you might already have guessed why we are doing this because we have done this so much that we now understand the need for it. So I'm just going to pass ant for now. The images is going to be an empty list. Category is going to be empty. String and price is going to be zero plus 10 semicolon. And you also, the quantity will be zero. After that, we have the tribe block for response, and we are sending response to this particular URL so we can copy this, paste it away. And we now, after the headers part and HTTP error handling year, we need to remove all of this for loop. And instead just have product equal to product dot from Jason. We have already done this. We are basically getting the Jason format. So we are taking that Jason and converting it to a product model. So we have response dot body and that's it. And now we just need to return that product. Now we are gonna use this function now, so we can just copy this, go to the deal of the day. And instead of returning all of this, We're gonna have in it state pass in the function as fetched deal of day, and then create that function. So we have fetched deal of the day, which is asynchronous and will not return anything. We are used to the convention by now. So we have product which can be nullable and just a device, if you've forgotten till now. And you're wondering why every time I use Nu so that we can just check if it is going to be empty. And now let's explain why we even created this empty model. Instead of this question, mark, as I said, this product can be Nu. So if we just check, if product is null, so suppose I check away a product is equal, equal to Nu. That would mean that we need to display a loader. That means that the data is being fetched. So thus, we are checking and putting a column away, but here we suppose we don't get the perfect deal of the day, because there are no products only there. So the user will continuously a loading bar. And the reason is, well, because this wasn't initialized and it was also nullable, but here, now it removes everything. And instead, if the product is now, we are going to show a loader. Otherwise, if it is empty So we can check away. Now we can't check product is empty because there is no function like that created on product model and it should not be created. How do we check if it's a product is an empty product? Like how so here, basically we are going to check if the product property on product, which is name is empty, then we are going to show a constant sized box, otherwise a column. Now we are gonna create the such deal of the day. So we'll have product equal to a weight and let's use home service. So we have final home services, home services equal to home services, take this home services and use home services dot fetch deal of the day, pass in the context. And yep. Now we will call set state so that the we build function rebuilds and yep. Look through. So now we have this loading bar showing up, let's restart the application and here we are still not seeing the correct deal of the day because we have not bounded, but we're not getting any errors as such. That's a very good thing. So what we need to do is go down here. And instead of returning so many image networks, I'm going to delete the rest of the three and keep one there so that I can map through them. So you are in the children. Also, I'm going to remove this list. And instead, what we are going to do is product dot images dot map, and we are going to map through them so that we can display them in a horizontal direction. If you see, we are displaying them in the horizontal direction, and that's how we are going to do it. Now, I'm going take this image network and paste it over here and also convert it to list. Don't forget to do that. If you don't convert it to a list, it won't know because this will return to us an it it, and two list just converts it to a list because that's what a wants list of widgets. And here we are returning a widget in case you return something like, you know, a string over, you can see, we get an error because type list of string, can't be assigned to the parameter type list of widget. So here we are returning the image.network and yeah, we have it. Great. Now let's restart our application. And The correct thing is still not showing up because we need to use E so we have E Pastin. Now, now we save this. We can see stainless steel bottle showing. And if we go at the top just to display a product image, which will be product dot images at zero, and also put that not now so that we can save it. And here we have it. And we are seeing two same images because here we have used it that way. We are product. We are mapping through the product images again, and again, if you want, you can ignore them, but I'm quite happy with what I've got after that. Whenever we click on this, we need to go to the product detail screen that we've already created. So what I'm going to do is wrap this entire column with a widget known as gesture detector, and also create a function wide navigate to details screen. Then I'm gonna call this navigator dot push named pass in the route name as product detail, screen dot route name with an argument. And here we need to pass in the argument, which will be the product variable that we have created at the top. So let's pass in product and this much is enough, so we can copy this, paste it down in the, on top property of this gesture detector after saving it this much, let's click away and here we have it. We are at the right place and it's showing everything very correctly. Super cool. Now the next thing is to work on the card feature. So whenever I click on this, add to card, I wanna see it over your, the displaying part and also this number should get updated. All right. So now what we're going to do is close all the other safe files, close this terminal, and now we are going to go to the user model.And in this user model, what we are going to have is another property, which is card that I commented. So in this card property, we need to have two things. So first of all, let's write the card property properly. So how is this card going to be like, well, first of all, it's an a, so let's quickly create this a kind of thing exactly that we did for ratings now in the rating. If you remember, we passed in the rating schema exactly for this, we're going to pass in the product schema, but cart, isn't just going to contain the product schema, right? It'll have the quantity as well. So we have the product schema as well, as in how much quantity do we want this product? So it's gonna be look, something like this. So the card a has a property of product. So let's wrap this. So card is going to have a property of products. So we're going to create like this and it'll have product called product schema. And we can just pass that in. Now we need to get this product schema because you have not imported it or even exported it. So here we are going to have this kind of destructuring. So to send a product, we are going to do something like this comma. We are going to send the product schema. We've seen this before to send two products. We are going to send it in a map or an object. So to pass in the object, we have product and product schema. Now, whenever we use product in some other route, so let's quickly go through some of the routes. We have product aware. So now to access that product, we need to wrap it with a Colibra so that we can restructure that particular object like we did over year. You can see that we did this for the product over year, the same thing we're going to have for O so now over year, there's nothing for product. And obviously in the product route, we're going to have that product. But so if we come to the user and again, call product schema, you can see we get the import. So let's quickly import that. And this comes in this format. Great. Now the next property that we need is the quantity. So here we can have quantity and passing the quantity, how it's going to look like now we are not going to create a separate quantity schema. So you are just manually type in number and required set to two. So yeah, we have the quantity property, which was of this structure. And we have product, which is of the following structure. Great. We are not passing in product away because we can't pass in model, right? It, we need to pass in the product schema. We've already discussed about that. So now, if I come to user JS the route, which we haven't yet created, so in the routes, you're going to create a new route called user RS. And this time I completely remember my mistakes from previous times, I'm going to require express, oh, sorry, let's close the files that are not required. So what I can have is remove models, the O files, the file, the admin we need just for reference and product and product model. So yeah, I'm going to require express, create the router, copy the post request because that's the very first request that we are going to need, add to card. And then we need module lot exports for this let's quickly rename, and then make sure to add the middleware in the index GS, which we've forgotten so many times or I've forgotten. All right. So we have user router passing the user router away. And even where now quickly, let's go to index projects and you require the user router. So we have user router. And now you can see project is expanding instead of creating so many routes your itself. We are just using a cleaner way of app dot use that makes a app less congested. And this looks great. So here we are going to have API of add to card, and this requires oath. So let's quickly import that. So we have cons equal to require dot slash middleware slash. Now we're going to have, first of all, remove all of these stuff. This is not needed. And what do we need? Well, first of all, we want to get the ID of the product so that we can find the product. So we will have constant ID equal to request dot body. Great. Now we can have product which will be equal to elevate product dot, find by ID. And then we need to pass in the particular ID that we got. Now, we also need to find the user because you're storing all of this end user model. And the reason we are storing the cart property and the user model is so that we don't need to fetch the data every time the user clicks on that card, I can write. So we are just going to display using provider, which will be a very neat way of doing it in my opinion, because we are using cart everywhere in our application right now to continuously post there and get from there, it's going to be a hectic job. So instead of doing that, we are going to save it in the provider, and that's why we are starting it in the user model. Also, even in that we are going to in this user.dot model, we are going to change there. So yeah, first of all, find the correct user. So we already know to find the correct user. We are going to avoid user dot, find by ID, pass in the request dot user as the user ID. And now we are gonna check if users card dot length is equal, equal to zero, Right? So now we are checking if the length of the card is zero. So if it is zero, then we need to do user dot card dot push. And I've already explained whenever there is an a, we need to push stuff. And this is like, add end dot. So we are going push to the end of the Ania, the product, and we need to exactly put it like this. And the next thing was quantity. And the quantity is going to be one because the user clicked on ad to cart. Only once, whenever the user clicks on the ad to cart, another time the quantity will increase. But whenever the user dot cart length is zero, it is going to be quantity one, because user is adding product for the very first time. Right else? What are we going to have now? Well, obviously you can use guard clauses away, but I'm not going to do that. I'm going to use nesting away. And this is very important now. So we are gonna have four loop for let I is equal to zero. I is less than User dot card link and increase I by one. So we have I plus plus, and we, you, we are looping through all the products and checking if the particular product that we have over here is already there in the user's cart. If it is already there, then we want to increase their quantity by one. Otherwise we need to just add that product for the very first time, just like we did over year. So we have that logic. So we have user dot card, I dot product dot underscore ID. So we have user dot card. I, so we get access to the very cart item so that we can look at the product because now if we come back over here, here, we could either use quantity or product. We are using product. And we are getting that products ID to get that products ID we are using underscore ID, because remember, underscore ID is what is given by mongoose or MongoDB. And what we are checking is is if it is equal to the product dot underscore ID, which is this, otherwise you could have just used this ID and it wouldn't matter, but it's the same thing after that, we can check this much. And I think this is a, and actually, sorry, my bad. You couldn't use ID over because if you use ID, it is of the type spring. But over here, the ID is of the type object ID because you you're not converting it to string, right? You could obviously do dot two string. And that's a method allowed in JavaScript, as well. As I said, it's very similar. So we have dot two string, and then you could compare with ID, but you are, we are just comparing two object ID now, object IDs, if you don't understand. So if we go to our products model and check, every ID is not a string. It is an object ID. Now object ID is randomly given by MongoDB and it's like a particular type for an ID in Mongos. So here we are not comparing strings. We are comparing object IDs. That's why we're not even using equal to equal to a layer. If we use equal to equal to, it'll not be a valid comparison under it'll always give false, even though both the same thing. The reason for that is we are comparing Mongo ID or Mongo DB ID. And that's why we are using equals great. Now, what you want to do is if that is the case, then we are going to create a flag at the top. So what we are going to have here is in the else, block, let, is product found equal to false. So if that product, if any existing product is found, we are going to set it to two. And the reason why we are not setting, you know, directly doing the stuff away is because it is in a loop. Now, first of all, why is this variable there? Which is just a flag to say that, yeah, we found the product now, what do we need to do? So now we're gonna have, is product set to true whenever we find it. So if that product is found, we need to just increment its value. Otherwise we need to add that new product To the card. Now, if we directly add the logic for adding to the cart wire, if that is equal to that, then that would mean we don't have to look forward. And if we look forward and find again, then we are adding it again. Now that would be really bad. So here, what we are going to do is if, if product found, so just like that we don't need to specify is equal, equal to two. We can just do Fs product found. Then we need to find that product. That means that the product already exists. So we need to find that particular product. And we gonna name it with three Ts because you already use product away. And we are going to use product with double T, uh, in just a second. So we have user dot card, which is an a, and JavaScript provides us with tons of functions. Another one of them is dot find on a, so here you can see find calls predicate once for each element of the IRA in ascending order, until it finds one where predicate returns two, as you can suggest the name itself sees it, that we are finding a product And we are using doublet. That's why the triplet and a single T O over and a singlet over year. Now, if that is confusing, you can rename it. But to your, essentially what we're doing is finding the product, which matches a certain criteria. So we have to pass in a certain criteria in the function. You can see this is a function format. And like, do we have single arrow operations as well? I'm not sure if I mentioned, but you can just have a single arrow in case you want to return something, which is just an Lineer, which is a shorthand for doing it even in dot, right? So you are, when do we want to return a product, right? Where if we find a product whose quantity want to increase, we use dot find. And what is the criteria to find that particular product? Well, the product's ID should match.So we have product with doublet, which is this dot product. Now not to get confused. Product is one of the products that user dot card has. We, you can consider it like looping. So we are looping through every card product and finding the particular product. So find is a short way of doing that. We could have used find as well, but the reason we did not do that is because we needed to use I. So we have product product, which is the product property in the user's cart. I could ensure it to you because we have not added anything to cart yet, but product. And instead of having your product, we could have quantity. Now, I think it explains well dot underscore ID. And we are again, comparing the MongoDB IDs so we can just do dot equals product dot underscore ID. Great. Now, after having access to that product and in case, you're wondering why we are not using this product that we already have, and that's because we are not storing that product anywhere. So now we can do is product with triple T, which is this one dot quantity and increase it by one, because that product already exists. We found that by looping. So if that product already exists, then we are just going to increase its quantity by one. Otherwise we are just going to push to card like this so we can have your like this now in case you're wondering, why did we have this condition away? If user dot card dot length is zero, then user dot card dot, push this. Now just think about it. If the carts length is zero, then will it run through all of this? So we have, I, less than zero, I is equal to zero. I is less than zero. So here, it's not going to run at all. And that's why we are not using that. After that we have the LS condition and here we are just going to use user is equal to avoid user dot say, because we updated the user's card, right? We don't need to do anything with product. Now. We don't really care about it, and we're not making any changes over there. After that. We just need to return a user. Now, after returning this user, you might have guessed. We need to update the provider and our client side. So let's quickly go over there and have that. So before even doing that, glad I remember it. We need to go to the user.dot and in your add a new generate a new thing. So the new thing that we have here is final list dynamic of card. And now we need to generate everything. And in case you're wondering why this is dynamic and not map of string of dynamic. And that's because when we get the data from our API, it'll not know that the card property that we extract is map does it'll give us an error, like type list.Dynamic is not a subtype of list, map, string, dynamic. You know, that's why we are using list dynamic. So here we need to add this required argument. So we have required this drug card. Then down here, we have card. Whenever we create two map, I don't think specifically we need that, but let's just have it. And even your, the card is going to be list of map of string, dynamic dot from, and pass in the elements, which will be map at card. You know that because when we send it over, we will have map dot card. Whenever we use from map map card, which can be in a label dot map X and it'll return map of string, dynamic dot from X. Great. Now, after having that, let's see why we are getting this error. We need to pass in a pattern thesis over year.And I think at the end also, let's see why we are getting this. We need to remove that semicolon. It just the pattern thesis and all should be good. Make sure this card property is like this by default, it would give something else, I guess. And that's why manually wrote it. Now we can go to the user provider and here add a card functionality, which will be by default NMP list. So now we can close this and now where do we wanna go? Well, if you come back over, you can see the add to card button is present on product detail screen. So let's go over there. And I see an error in the part, so we can go there. And in the odd service, we can add the empty card that we need right now after achieving that we can go to the product detail screen and in the services of that, the first functionality that we want is going to be a post request again, so we can copy this, paste it. And now we're gonna name this, let's say, add to cart. And this function is going to be pretty usable because we're going to use this add to cart, even in the cart screen, when we need to incremented by one. And we here, we need the required as built context and the product so that we can get the products ID. After that, we need the user provider as well. We need to send a post request and here we just need to send in the ID, which is product ID. We have passed in the correct head. After that, we need to do the error handling part. Now the error handling part is going, be something tough. So we are going to make it very easy for us. So as we already know, we will get the card. If you go to the user or GS part in the routes, we are sending user away. Now, instead of just manually doing, you know, something like user dot from map and pass in the re body, instead of doing that while Jason decoding it and all that stuff, you know, instead of doing all of this work, instead of updating this entire user, which will lead to us going back to the O screen because we updated the user's map for some time, it was Nu. So that kind of errors we will get. You can try it on your own. You will get it. I face the same thing. So what I've done instead is in the user model, again, let's go there. Your let's go on the top, click on this ball, bike in and create copy with class. With this copy class, we'll be able to only use and copy with one value. For example, if we have the ID name, email password, all of this typed in, and we just need to pass in the token as, uh, sorry, card as a different thing, then we can use copy with it'll copy with all the other features that it has along with this, it is similar to, you know, theme of dot context dot, uh, you know, theme dot, dot copy with it's doing the exactly the same thing. So we can create this copy with function.Now, what we can do is go to the product detail screen and your have user provider user, which is the current user with all its details dot copy with now, since this is an instance of the user class, we get access to this copy with function, and now we need to copy with this card and this card should pass in the Jason decode, which is response dot body. If we send in response dot body, we are sending in the whole user card. We don't want to send that. So we will just send in the card. After decoding this, Jason, we get access to card property, and then we are just doing that and we're gonna set, uh, store it in a separate variable, but now we need to update this right. User provider is still not updated to update it. We always used user dot set user from model. We don't want to do that user dot set user. So whenever we wanted to set a new user, we would do user dot set user. You saw that user provider dot set user, sorry, but now we can't do that because set user takes in a spring and we don't have a string anymore. We have a user model. So what now we are going to do is go to the user provider class. Let's go there and here create a new function. So let's create void set user from model, as the name suggests it'll take in the parameter type as a user. And then it'll make sure that the private variable user that we have a year is equal to this parameter type user. And then we just need to set notify listeners to notify all the listeners. After that, we can just come over here and pass in user provider dot set user from model and pass in the correct user.Sweet. So after that, we can save this and let's see what we will get. So just to see if there is any changes, what we can do is go to the bottom bar. And in here we can have final user card link equal to now, instead of typing in provider dot of context, all of that stuff. Let's first of all, import provider, we can use a short syntax that I'm not used till now. So we can use context.watch. This is a short syntax for provider dot context, and we have it and also person user provider over here. And yeah, we have it. And now we can have dot user dot card link. So this will Fe us the user's card link. We can copy this, go to the badge. And instead of passing in two, we are going to pass in user car length. Also remove this constant, and you convert this to a string create, uh, if you come aware, we are getting this error because we need to restart it. And here we have it, zero displaying, which is a correct card link. Now, if I click away, click on, add to card, come back away, nothing has changed. And that's because you have not bound this function of card to card to our product detail screen. So let's use that. Let's also go down. So we are gonna create a new function called add to cart. We will have product detailed services dot, add to cart, pass in the context, the product, and to get the product. We will just do widget dot product. Great. Now we can take this void, add to cart and go down where we have add to cart and pass it. The on tap this, add to cart and after saving it, we can click on, add to cart. You can see product validation, fail ratings, zero rating. Let's quickly see that path rating is required. Let's see. Why do we need that? So if we go to add to card, add to card and we have cost and rate product over a year, so we need to change that to add to card. Always keep making stupid errors, but yeah, we have it. Now let's click on, add to card. Let's go back. You can see one away. And in case we, again, type, add, click on, add to card. It should not give us two. It should only give us one with increased quantity. So if I click on, add to cart, it's tell one. But if we go to our users, let's click on refresh your fresh here. Let's scroll down just to find the user via the cart, the zeroth object, quantity here. You can see two random ID generated, and then we have our product object and we click stainless steel. Now what do we do if we have MacBook? So let's quickly type in MacBook. So let's quickly type in MacBook and click on enter. And you can see in the DAC console, we have this keyboard error. So we are gonna restart it and try it again. It won't happen on release version. So don't worry. Now, if I click on enter MacBook air, let's click on, add to card, go over there. We have two showing up sweet. So now our cart function is working. Let's display it away, which will be fairly easy because we are gonna copy paste a lot of code from searched product. All right. So now what we're going to do is close. All the safe files, minimize all the folders that we have and now create a new feature called card. Also let's minimize account now in the card, we're going to have screens and services. Obviously the services will now consist of decrementing the cart, so that's fine. And now we need cart screen.Let's quickly build out the card screen and display the products that we have. We are waiting for it. So we have a state full widget where we're gonna call this as a cart screen and create a constant cart screen. After that, we are going to return a scaffold and go to the home screen to copy this app bar, which we've already copied away. Let's paste it down there. After that, we are going to create global variables. Copy this, obviously copy the function so that we can navigate the search screen and paste it away. Yeah. After that, we are going to import them. Great. Now, what we want to do is after this app bar, let's bind this to our bottom bar so that we see the correct cart screen and see it on the screen. So we have constant cart screen and pass it away.Now let's restart our app. If we go to this card, we see the correct thing. And it's the same thing as this one. Now in the home, sorry, in the card screen, let's close both of them in the body. Now we need a single child scroll view, and I've already, uh, told you the purpose of this single child scroll view. After that we need a child and the child is going to be a column and the column is going to be children of first of all, an address box. This address box is going to consist of the address, no brainer. Yeah. This address and save this much. We see the address box showing up correctly. After that we need the subtitle for that. We are going create a separate widget. So in the cart we have widgets in person, something known as card sub total, the card subtotal.dot let's import the material dot for it. Call it as a state, less widget and call this card subtotal you in the stateless widget. We are going to, first of all, have final user equal to provider dot of context. So let's quickly add that. And actually let's use context dot, watch, use the user provider and then use the user's property on it. After that, yeah. Margin and from cons inserts dot all. We want a margin of 10. After that, we need a child of row. And in that row, we are going to have subtotal with 1500. You can always use a text span, but I'm just showing you an alternate approach of doing it. So we have a constant text that says subtotal. We are going to leave some space and not put a colon and put in a style as textile font size of 20. After that, we need a text which will show the total subtotal. Now to calculate the subtotal. We are going to do this in the build function itself. So we have end sum equal to zero. And here we have user dot card and we need to map through all the elements of the user dot card so that we can get that price and add it to the sum. So we have E and now we can use some plus equals E at quantity. And since this is a map, but we have used it as a dynamic, we can use E quantity into E product. Now, if you are wondering why we are doing what we are doing while we are just while we are just using quantity E quantity and multiplying it with the product's price, because the subtotal will be how many products you buy. So in case of a year, let's see we have iPhone and we have three iPhones. We want to display 4,500. So if we click on three, it'll be 4,500. That's what we are doing. Multiplying quantity with products, price. And then we are going to treat them as an NGER because they don't know. And obviously convert this to list later on. Otherwise it won't do anything at all. It will stay in an Iterable. After that, we can take the sum, pass it in the text. So let's copy the text. Also pass it in the text, which has the font size of 20, but font. Weight is font, wait, bull. And here, the price is going to be slash dollar dollar sum. So that will make it dollar with whatever sum it is like 20. Now we save this much, come away. We can't see anything because we're not bound this widget, but yeah, we have it. Now let's go away and have constant cart, subtotal and great. Also, we need to import it. So let's quickly import it. Now, if you come aware, you can see sub total 1019. I'm not sure about how much did you buy that? You're getting this, but we'll verify once we get the products showing up. So now the next thing is this button so well for that, we already know what we are going to use. It's going to be custom button. Your, the text is going to be proceed to buy pass in the, how many items there are. You can see one items, three gonna have dollar user.card.link. And now we need to create this user. So we can just come up here, take this user, paste it in the build function, import user provider, and also import watch from provider.dot. And yeah, you have it. user.card.link items. Then we need an on tap. So we have on tap. And after seeing this much, we can see this, but now we, first of all, need to shrink it size and then change its color. Let's do it together. So we have padding rapid with padding of six, eight. And after that, the color is going to be colors dot yellow at 600. And now if we come aware, we see a correcting showing up after that, we need a slide border below which we can show this product item. So what we are to have is a constant size box of height, 15, then a container which will be of the color colors dot Blackwell. And now we want it to look very slight. You know, black 12 is having a lot of impact so we can have dot with opacity, not 0.8, but 0.08, which is very, very mild. And obviously mention a height which would be one Saving this much. We see correct things showing up after that. We can, again, leave a space. We have not left space over here, but now I realize this problem so I can leave this. ER, let's say five only. And then we want to display the list of products for the list of products. We are going to use ListView dot builder, get a context and an index after which we are also going to get an item count. So we have item count. And now the item count, first of all, is going be user.card.link and the item builder for that, we are gonna create a different widget altogether. So in this widgets, we are going to have card underscore product dot and not dot product, but card product. After that, we're gonna import material dot, create a stateless widget, call it card product. And this card product is going to be very similar to the searched product that we've already created. So what I'm going to do is first of all, even convert it to state full widget. The reason for that is we are going to click on increase and decrease product, right? So that state is going to change. So we need to make sure we add that After that we are going to go to the search product and copy the whole thing from the search product and then make some changes. So I'm going to copy this entire column, paste it over here and let's see the errors. Well, first of all, we need to remove stars because we don't need to display the stars. Then we need the product name. Well, we are going to get that from state full widget. I mean, this is a card, right? So we just need its index so that we can display. So we have final index required this dot index. And based on this index, we can show the card products. So obviously in the build function, we will have final product, which will be equal to provider. And instead of using provider again, I'm used to it. So we can have, watch and pass in user provider Dot user dot card, and we want to get access to that particular product. So we're going to have widget index. Great. Now we have that product, but now for the ease of our using itself, what we're going to do is pretty smart. You can see that we have product, we are going to name this. Let's say product card, very less descriptive, but I know you can change it. I'm very bad at naming. So you're, you're going to do final product, which is equal to product from map. This will allow us to get, you know, auto completion and will make sure that we don't have to use those annoying brackets because they reduce, they increase our chance of hypos and bugs. So yeah, we can just pass in product dot product card. I'm a big fan of using these models because they make my life much more easier. So I can go to the down and we have the product created already. And now just to see what we have and then make certain changes more. What I'm going to do is return the card product Ania. So yeah, we have it. We have mentioned the index as well. And now we are not seeing anything. We can see list view. Builder has an error Ania, and that error can be resolved by either wrapping it with expanded or setting shrink up to two.Your type is not a subtype of type it dynamic. If we just restart our app, it won't do anything, but it will let us know what we are doing wrong somewhere. And the reason you're getting this issue is if we go to the card product, we are passed in product from product card, but the product card that we're sending includes both product and the quantity. We forgot to take that into account. So we have card, but now that card consists of an object. So let's see we are, we have an object which has product and there is the product object. And after that, we also have quantity. So it passed in this entire object, which is giving us the issue. So here we want to specifically tell that we have product that we have passed in saving this much. We can see correct things showing up. That's insane. All of these things are matching. That's pretty cool to see. Now, the only thing that we need to change is this button part. So let's quickly create those buttons. So we're going to have them after the in-stock part. Let's close this and here in the row, just below this image.network and column, and actually not even in the row, because if we put it in the row, it'll come back over here. We don't want it over year. We want it over year. So we wanna pass this below the row, which is in column because we have a column first. So here we want it. So now we are just going to have a container for increment increment. But so here we have margin, which will be constant edge inserts dot all 10. Then we need a child of row <affirmative>. And that role is because we need these three places. So you are in the children. Well, first of all, we need main access alignment, which is the main access alignment or space between. And then we have a container and we have a decoration which will be boxed decoration. And then we pass in border, which will be border dot all. And then the color will be colors.black, twelves and width will be 1.5. After saving this much, we can't see anything on the screen, but that's fine. We are gonna have a border radius of border radius dot circular five. And we are just designing the outside of this. You know, this part away are. So now we are going to have this and then the color, which will be colors.black twelves. After that, we need a child in the container itself, which will be a row. And in that row, we are gonna have children, which will first give the icon of this minus sign. So we can have container again, which will be of the width, 35 and height 32. And now we need to align this container. That's why we and container, otherwise we use wide size box. You can see that. So yeah, we gonna have alignment as alignment.center and then the child has constant. I can, I can start to remove which size 18 let's save this much and come back away. You can see minus sign is coming and it's looking good after that, we need this quantity showing I icon, but for quantity showing I icon the color should be white. So what I can do is first of all, wrap this container with an ankle widget, which we will do later on because we need to decrement after that we have container, which just shows a text, which will be of the quantity. So we'll have quantity. So let's quickly go up and have final quantity equal to product card quantity. Let's take that quantity, go down here, pass the quantity and pass in dot two string because this is going to be a number right now. If we go where you can see two is showing up, but we need to change its colors. So to change its color, we can just wrap it with a decorated box and so box, instead of wrapping it with a Container, we are doing decorated box, and then we can pass in box decoration. The border will be border dot, all color as colors.black twelves with 1.5 and yeah, save it, come back away. There's no big change as such. So now we are going to pass in the color, which will be colors dropped white. Now you'll see the color change, which is this color, but we also have a bit of, you know, this color border that we have. And then we just need to make sure that there is no, you know, border radius. So we can just pass in border radius as border radius, circular, zero Saving this much. We come back and there's no border this. You can see the border radius is diminishing for this, this part. If you zoom in and see it after that, we again need this container. Actually let's copy this container because it's going to be pretty similar to this. Just an I can change will be, which will be Ikes dot, add no, save this much. And we have, it looks exactly like your, and it looks pretty good. And here we are seeing the correct, you know, the product quantity as well. Now let's just calculate what we serve 1090. So we have one product of MacBook and one. So we have 9 99 plus two times 20, which is 20. So 1019. This is absolutely correct. Now, whenever we click on this, we need to increase the quantity. We have already created a function for that we need to create for decreased quantity. So let's quickly bind that, increase quantity one and create one for decreased quantity. So we will have final product details, services, product details, services, equal to product details services. And then we are gonna create a function, void increase, quantity Product product, and now we wanna increase this product's quantity. So we have product details, services dot, add to card, and we've already added the logic for adding to card. You can see that we have add to card. We passed in the product and we are its quantity. And we've already added the feature of checking. If the cart already exists, then we just need to add one to this quantity. And we've done all that stuff already. So we don't need to worry about it as such. So we can just reuse this function. And it's pretty cool. Now we can just go down, use this increased quantity again. So you are wrap this container with an INEL widget or a gesture detector, whatever you feel better with. I think I'll use inal. So that user feels that yeah, there clicking something, you know, not just a stupid button, you know, it gives a kind of good feeling. So yeah, we are gonna have an on tap and then pass in the function, which will be increased quantity pass in the product, which we already have done. And yep. Now if we click on this product, it is three. This is two, and it's increasing real time. This is absolutely insane. Now the same thing we are going to have for decrease quantity so we can create a services of card services. Otherwise you can just do it in product detailed services, but I think it's cleaner to have card services as well because this function is only used over year in this card services. Obviously we are going to go to the product details services and copy this entire file and paste it over here. Now let's rename stuff. We have card services. We are going to have well remove rate to product. We don't need that. And in Europe, we are going to have this named as removed from card. This is going to be a required product field. We are going to get the user provider and then we are going to pass in the API that is HTTP delete. This is something new. So we, we looked at get update and post, but we didn't look at delete. So this is the final crude function, which will also tell you that we are nearing to the end. We're coming very close to the end of this application. There are just a few features left. You can look in the times cams below, but the point is we are using delete away. So obviously there is no body aware and for delete, you're not going to pass in anybody, but we are going to use that URL format that we had. So we have API slash remove from cart and then pass in the product ID in the URL and already know how we are going to access it in the server. We are going to use requests, but here we can worry about product ID passing it in carefully. After that, after that is done, good enough. We're going to get user user. We need to copy that card and set user from model, all of that, similar to add to card. Now we just need to create a different URL for this thing. So I think I'll just copy this part and go to user dot JS. And in the routes, we are going to create a delete post. I'm just going to copy this and paste it away. And this is going be called user dot delete. And again, we need to copy that URL. So you are copy it past it away, and we are going to pass in the ID. Well, the ID can be accessed using request paras and your make sure to add this call and don't forget it by any chance. And here we are going to use request dot paras as the ID. Otherwise you can just use request per ID. I mean, both of them are the same thing, but I just wanted to show you another way of doing it, which is this. After that, we are going to find the product. We are going to find the user and you're we are, we do not want is product found and all of that stuff, we already know the product is there. That's why the user is even able to click on that. Remove from card button Here we are going to remove, this is product found part. Even this L block, this F block, and even this lead variable is product found variable. Now we are gonna check from going from zero to card.link. I plus plus checking if user product ID is equal to the product ID that we have, then we are going to do user dot card splice because you want remove it. And as you already know, splice helps us with that. Just to make you remember again, what the slice will do. It'll delete the product based on whatever you enter. So we need to enter the start number and how many elements do we need to delete after that? And in case you're wondering why we are not using find function over on user dot card dot fine. And that's exactly for this reason we're using. I, we want the I so that we can splice it out. So yeah, we have, I comma one and after splicing it, we are good to go. So if the user card's product exists and if it is equal, then we need to splice it out. Otherwise we just need to display the card. And actually not this, we will splice this out, but now the thing is this product ID equals to this product ID. I mean the card's product ID that while we are looping is equal to the product ID that we found, then we need to splice it up. But what if the quantity is one, it'll just change it quantity to zero, but it'll still say stay in this cart object as an area. And it'll still display on the screen showing that this is zero. So what we need to do to avoid overcrowding in our database is check your, if user dot cart I dot quantity is equal, equal to one. So when the user clicks on the delete button and we get called to this, remove from cart API, then we will check if the quantity is one, that means that the user is just about to remove this entire product. Then we are just going to use this user dot card splice. Otherwise we are going to use user dot cardThis line, but here instead of equal, equal to we'll have minus equal to one. That means user user dot I dot quantity will be equal to user dot I dot quantity minus one. It'll decrease its value by one. And in case you get confused and you use user dot card, I dot product dot quantity. Don't do that. You know, we don't need to use that because it'll give us the number of total products left, not the quantity we will have in the product. So we are essentially changing the products, quantity over here, both of these match. So if you decrease this products, quantity wouldn't even matter because you're not even looking at it. So we are just decreasing it by one. So we are just going to have user dot card. I quantity minus equal to one. After that, we are going to save it and return it. Now let's bind this function to our card per screen. Let's go at the drop and actually in the card product, we'll avoid decreased quantity and use final card services, card services, equal to card services, take this card services and have dot removed from card pass in the context and the product, and then use this decreased quantity. So we can Wrap <affirmative> wrap this container with an ink widget, use the on tap feature. And here we haveDecreased quantity passing the required product and boom, we have it. Now, if I click on minus sign, we set it to two. We set this to one, we set this to two and the value is also changing. If I restart the application, we should see the same state of our application. So if I come where one and two, 2008, now the next thing we need to work on is whenever we click on this, we get to an address box form. And there we do some validations to check. If the user has already entered the address, if the user has already entered the address, then we give them an input box saying that you want to use this address or the one that you want to newly form it. And then we can click on the apple or Google pay, whatever is provided and continue with that. Let's quickly do that. All right. So now for the address screen, I'm gonna close all the safe one again, and here I'm gonna create a new feature called address. This will again have screens and services, so let's quickly create them. And now this screen will have address Screened or dot we're going import material dot, create a state full widget, and then call this address screen. After that, we are going to call this as a constant constructor and here we are going to return a scaffold, which will have a simple app bar. If you come away, this is the design of the application. So you can see this is a pretty basic thing. We just have a gradient. So now just to have a gradient, what we're going to do is go to the home screen, copy this app bar, tell let's say year only, and then add the remaining parent thesis by ourselves. We can do that much after that. We will import this package and also this plan thesis. Great. Now, whenever I click on this, I wanna navigate over year. So obviously we are going to call the static constant string, route name, call address, and we are not going to get any constructive receiver or anything. So that's good. Now we can copy this address. Screen, go to the router, create a new route for it. And we will call this address, screen, route name, nothing in the construction. So let's remove that and have address screen, remove this from the construction as well, and call this as a constant address screen. Now, whenever we go by your, whenever we click on this proceed to buy. So let's go to the card screen and create a function called navigate to address. So let's copy this, paste it here and have navigate to address. And To this address, we are just going to pass in address green route name. I don't think need anything else in case we need, we have to make that changes. So let's quickly remove that out and here navigate to address in that on tap. We are going to pass in the navigate to address function here. The argument has nothing. So let's have this much and yep. Whenever we click on this, we come back to the screen. Great. Now, what is this logic going to be like? I I've already mentioned it to you. Whenever we have an address, then we make sure that we show this otherwise. And as the user, if they want to use this, otherwise the form. So now we are going to just have a form in the address screen. So for that form, let's close the card screen and have, uh, screen dot file where we are going to con copy all the form content that we have and paste it in the air scaffold, which is this body and paste it down here. After that, we need a custom text field. So we are gonna import that library. We also need these controller. So let's see what controllers we need. These four controllers. So well, let's name them. We have flat house number building. After that, we have area street. Then we have pin code. After that, we need one more, which is town and city. So let's copy this much, pasted down here and have town or city and import custom button. So let's import that library and here in the on tap, we will validate later on, but for now let's remove that and the text is not gonna be sign up. And actually we don't even need this custom, but we need an apple pay button right now quickly create all of these custom text, field controllers and a sign up form key. So let's quickly go on the top and have those text editing controllers created. So we have text editing controller. First of all, flat building controller, which will be equal to text editing controller. After that we pasted three, four more times, three more times. Actually we have area controller, pin code controller, and finally city controller. Now copy these controllers. So we have flat building controller, area controller, then the pin code controller. And finally the city controller also dispose them off and create the global variable. So take them and dispose it over year. And we going do it more times. So we have four more times area controller or dispo pin code controller or CD controller dot dispose. Also create a global key, which will be final underscore, not Nell final address form key, which will be equal to global key. And then we are going to have a form state. We have already looked at it. We created this odd screen. So let's take this address form key, paste it in the signup form key and have that done. Now, let's see what we are getting. This looks good enough. Now let's create the conditional logic for showing this address if it exists in the first place. So what are we gonna have? Well, first of all, get, let's get the user address. So we have variable address equal to context.watch, and here we need to import it. So let's get that import provider. And this will be of the type user provider person user away and also dot address because we need to get the user's address. And now we need to check before entering the form. So we will check your, and before even checking, let's actually add a padding to this because you can see there's no space left from the left. So we can wrap this with the padding widget, save this much and you have it. <inaudible>. Now we are going to have conditional logic, but before that let's even add the single child scroll view so that it's scrollable. And when the screen size decreases, we've discussed a lot about this, but if the screen size discusses, uh, decreases, it's going to be a much, much big use to us when you use smaller screen size. You'll notice that. So you're in the column, in the form before entering the form, you, we are going to first have a column. And in this column, we are going to check if address that we have is not empty. Then we want to display this container with the text. So again, this will be a column and why this is a column well, so that we can add this text and even this or text that we have along with the size to box away. That's why we are having them. So we have children and in the children, we're going to have a container of decoration, which will be box decoration, have border, which will be border dot, all pass in the color, which will be colors.black 12. After that, in the container, we will have child and the child will be a text saying that this is the address, and then style it out, which will be Constant textile and phone size 18.After that, let's see what we're getting. We can't see anything because address is empty in case we change the value for now. So let's say 1 0, 1 fake street and come back. You can see fake street showing up just for designing. We are going to use this fake address, but after we do that designing part, we can again, come back to this address. So you are in the chart. We're going to wrap this with a padding so that it looks much, much neater and better. So we have, PAing also, we can specify a width of double dot infinity. This looks great. After that, we will have a size box of height 20 after that a constant text saying this is, or, and then have a style of textile. Well, font size 18, because we want the size to be lower than the usual, a higher than the usual size. Sorry, because you can see this is seemingly very big. Also after this, we, again need to leave some space for the bottom so we can copy this size box, paste it down here, come back. This looks great. After that, we finally need an apple or a Google pay button. So for that, we are going to use this play pay plugin so we can copy this Use dot, add dependency to add this. We need to stop the app execution and let's read through the documentation. You can see it only supports Android and iOS still. Now that was the problem in case this get gets updated in the future, I'll add a, a video or a documentation using which you can add it to your own app in the pin, common below, be on a lookout for that. So you, we have apple pay and it tells us to get started in construction. I'm going to use a test payment service so that I can test it out. But if you are a business and looking forward to it, this is a pretty well-documented thing. You can take a look at it. I'll if I do this, and if I cover this part, it'll be the exact same things mentioned away. So I don't find the need to do it again. After this, we just need to add this to our dependency, which we already did. And here you can see, create a payment profile with a desired configuration for your payment, either using a local file or loading it from a remote server, we are going to use a local file for it and to use the local file. We're going to go there to this repository link is mentioned in the description below in the assets where it is images. We are going to copy both of these files, apple pay Jason and GP. Do Jason, if you're not on macwas, then don't worry. Don't have apple paid Jason, but in case you want apple pay, it's great enough. You can have it. It'll display on Android phones, but I would recommend you to not use this. We will just use GP for Android devices and we are going to test it on Android as well.We have not used it till now, but that's fine. Where in the assets I've already installed it. So I'm just going to copy it. So I'm just going to take these files and past them in the assets, make sure they're in the assets, not, not in the images folder. And now what we need to do is go to the pop spec dot file and add these two assets. I'm just going to copy this path and pass in apple, pay dot Jason. If we see, let's see the name, if it's correct or not apple paid or Jason, correct. And we don't need to add this slash because this is adjacent file. This is a file. This was a folder. And we needed to include all the images in this folder. But for Jason, we don't need to do that. And exactly the same for GP adjacent.If you want, you could have done assets, but the thing is it would've loaded unnecessary assets in a file as well in case our app gets bigger. So that would mean it would cause the app memory to increase. And that's why I'm not doing that. Great. Having that and the pay plugin install. I'm gonna get out of this form also. And you're introduce the apple pay button. Now, obviously I have to run this, but before that, I need to set up the payment configuration asset. And this is basically asking for the payment config file that we've just created. And then we just need to pass in apple, pay Jason, no need to mention assets slash images and all of that part because you are in the documentation. It is already written that we need to pass it in the assets folder. Example, meaning the name of your project slash assets folder. So your it'll just navigate through that and check if there is apple pay. If there is, if it is mentioned in any other folder, it'll give us an error and on payment result, we need to create a function for that. So let's quickly create that on the top. It'll be called void on apple pay result. Yeah, we are going to get the result and yep, that's it. Let's go down again. Passing the result after that we need payment items, which for now is going to be, nullable actually, let's create it at the top again. So it'll be list of payment item called payment items, which will be an Mt list for now, but we're updated later on and later on, I mean in just some time and now let's run our application to see what we are getting till now. I'll go in the DVA console and see, and your build has failed because here you can see, this is only available in iOS 11.0 or newer.So we need to go to our port file and change this platform. iOS version from nine to let's say 11. Now save this much, open up a new terminal. And in the Amazon clone tutorial route for root folder, we are going to go to the iOS. And in there we are going to run port install here. You can see port installation was completed. Now I can clear it, go back to the root folder again, clear it, and then run the file. After that, we are going to stop all of this and let's see what we are getting now. All right. So app has loaded up and now if we go to our card, click on proceed to buy two items. We can see the app will pay button let's design. This app will be button now. So your first of all, we want the width to be increased. So we will have double infinity, whatever space we get in terms of width here, we have it. Now let's specify the style secure. We want to apple pay button style dot and you get a lot of values to choose from. What I'm going to do is white. Let's see what we get in white, not looking good. So let's try a different thing. Let's say white outline. Let's save this much and here we have apple pay. So let's change its type. So we have apple pay button type buy because we need to buy nothing else. Let's save this much and let's restart our application because for some change thing, for some reason, the changes aren't showing up, let's quickly click on, proceed to buy, and you can see there are certain changes created. Now, after that, we need some spacing from the top. So what we can have is a constant size box of height, 10 given also let's increase its height.So what we can have is over here, the height as 50 let's save this much looks good enough. Let's add some margin from the top. Again, not just this, you know, we have size, but a year also, it gives us margin, which will be constant sets dot only. And from the top 15 using this also we have the top margin creator. Great. So now let's add the apple pay button so we can have constant sized box. Let's remove it from here and paste it over here. We have constant size box of height, 10, leave some white space, and now we are going to have Google pay button. So we have Google pay button. We need to pass in the payment configuration asset as G chase. Then the on pay result, payment result, which will be on Google pay results, just like on apple pay results.So we are just going to copy this, paste it away and have on Google pay result, paste it away and have on Google pay result. After that we have passed in the payment items. We won't be able to see it because apple doesn't support viewing other pay services. So on iPhone only Google pay button is visible. Only I apple pay button is visible. So that's the issue. So let's specify certain properties that I've tried and tested on Android phone earlier so that, you know, you can copy them. And when we check it on Android, you can see that if you're checking on Android already, that's great. Let me know in the comment section, if I got it right. So we are gonna have Google play button style as black and type is going to be Google pay button type.by and type buy. After that, we already need this margin. So let's add that margin. And also don't forget to add a loading indicator, which will be just a constant centered child, widget of circular progress indicator. Having that much done. We have apple and Google pay buttons ready. Now, if we click on them, nothing really is happening. And that's because we have not mentioned payment items anywhere. The payment item is going to consist of the total bill in our application. If you want, you can mention each and every item that the payment items has, like, you know, if we added iPhone max and everything, you can create those payment items, but here we are just going to store the total amount. So to get the total amount, I think we have to use this. So we have final spring amount and we'll call this total amount and require it from the structor. So let's quickly click on the bell by and generate total amount construc. Now we need to go to the router.dot. Also, save this, go to the router.dot, add this line, paste it away. And we know this is called total amount. We need to pass it in the address screen. So we have total amount, total amount, and we need to treat it as a string. Yeah, we have it. Now, whenever we use this address screen, which is cart screen, we need to make sure that we pass in the arguments, which is the total price that it took us. So now we will have, and some, and now we need to convert this argument to some dot two string. Great. Now we can come back over here and now we need to pass in that like this. If we store it like this, it'll call the function. We don't need to call the function. We need to store the address of this function. And that's why we are using this kind of thing. And now we need to pass in the sum, which will be the some that we created over your, and we actually haven't created that. So let's create it very quickly. Well, we can just copy it and we can copy it from card subtotal. So let's quickly copy this card, paste it over your, and click close the cards up total part. And now we need to pass in the sum, which we already did. Great. Now, whenever we let's restart our application, click on router.do. And even in the, in it state, let's create that part. So whenever we create the, in it state, what we need to do is add the payment items, this amount. So we have payment items dot add, and then we will have this payment item that we need to pass in. So the amount is widget, total amount, and this is a string. Then we have the label called total amount and the status is going to be payment item, status dot, and you can see, what is this item status like? Is it final price? Or the bargainer can negotiate or it's not known to us so we can have final price done and great after having this much done, we can come over here, click on, proceed to buy two items, click on, buy with pay. And yeah, we have it. The correct amount is showing your $2,008. Yeah, we have the correct name as well. And now if we just click on done, we can even click on pay with passcode. Now that is not going to happen right now because we have not validated on apple pay result in all of that stuff. And that's mainly because we still need to make one more validation. So whenever the user clicks on this buy with apple pay or Google, what we need to check is if the user is using this address that they have already provided us with, or this form, if they're using this address, Then <affirmative> then so how are we going to validate that? Right? So you are basically, we are going to check if the user has not entered in any of our forms, anything that means everything is blank. Then we are going to use this thing. Otherwise we are going to ask them to validate this form. So we are going to create a new third function. We look into this on apple pay result on Google pay results later on, but this we have pay pressed and this will get us the address from the provider. Let's name it that only. So this address from provider will fetch us the value from this address that we will fetch from provider. But for now, just for testing, we have changed it. And here we are going to first create a variable called string address to be used. So let's quickly create that and have string address to be used is equal to empty. Then we are going to take this address to be used and pass it in away. So we have address to be used as empty again. So if the user clicks on the pay button twice, we need to make sure that we use different addresses every time. And the preexisting value gets removed. After that, we need to check if the user is using the form or the address from provider. So here we are just checking bullion S form. And we just need to check if all of these are empty or not. So we are just going to use flat building controller, text.is not empty or, or, and then just use it three to four more times. So let's quickly copy that paste it, paste it, paste it, and I think paste it. Yeah. Now save this much. And now we will use this area controller, pin code controller and city controller. We are just checking is they're not empty. If any of the controllers are false, meaning any of the controllers are empty. Then the form is also false. And that means we don't need to use the form here. We will check if it is form then. So if the form is true, then we just need to validate the form, right? So we just use address form key, current state validate. So if it is a form, then we need to make sure that it validates. And if the ations also go well, then the address to be used is equal to dollar flat building controller text let's have this. And I think I pasted it twice. So let me remove it once. So this is the layout flat building controller text. Then we need to pass in the area controller. So we have 1 0, 1, let's say 1 0, 1 building. Then we have the area controller. So let's say this is some area like wall street. And just making that up. Then we are going to have a city controller. So we have city controller text, And then we are going to have an fin just to show a pin code. So we have dollar pin code controller dot text. After that we are going to save this much. And this is the address we need to show, show. Otherwise we need to throw an exception. We can't just use, uh, you know, a snack bar. Otherwise it'll further execute our application, but we don't want that. We just want to show an error on the screen. So we will have please enter all the values. Also, we are doing this through exception because we are going to use this pay press on, on tap of this function. So whenever we click on the on tap, and if there is no exception, then the button like this will pop up and it'll still allow. Even if the user is not authenticated, it'll still allow to show all of this, uh, you know, this payment methods. We don't want that. So here we are throwing an exception so that we get the exception in the DB itself and the button doesn't show up. After that, we gonna have an LZ checking. If address from provider is not empty. So if address from provider is not empty also, I think we forgot a brace away. Yeah, this is the F and LS block, but this L just stands for this main block away. So this block away. So we have address from provider. If it is not empty, then the address to be used is going to be addressed from provider, right? If it is not empty, then obviously we are going to take that. Otherwise we need to show a snack bar saying error. And this is very rare. It's just for error handing, but Great. We have imported that now. Let's see what errors you're getting down, but, and the error is there because we added an extra brace. So let's remove that extra brace and you all the errors go away. Now we just need to take this pay press and add it to the on press. So let's go down to Google pay button and have on press passed in. So we need to pass in the pay press and the address which will be from the provider. Again, we can copy this, pass it to the apple pay button. So let's go there And your pass it in, in the pay. Sorry on press pass in this sweet. So now if we see click on buy with pay, it'll select the address. So let's also print the address that it is selecting. So we will have print address to be used, and let's see what address gets outputted. So I'm just going to restart the whole thing. And if it's one zero and fake street, then that would mean that we are using the address and we have not filled the form. So now, if I click on buy with apple pay, you can see one zero and fake street, Austin, that's working. Now, if I type, let's say 1 0 1, click on buy with pay, you can see enter your area street. And all of that, you are an exception should come in that enter all the values. And also you can see the apple pay button. Doesn't show up. If you just comment this line out and the LS condition also, it'll throw you it'll. After showing this validation error, it'll also show you the button. That's not what you want. Great. So now I'm just going to enter everything. So let's say wall street Pin code will be, let's say thousand one and the town will be Washington and let's click on, buy with pay and come back over here. This is a thing that we are using exactly what we want. Awesome. Now we just need to create an API because on apple pay result on Google pay result, handles the authentication part. So these functions will get called only when there is success. So if the user suppose fails the success or just clicks on X, these functions won't be called. So we just need to work on the API part of it so that we store the order. And then afterwards, we just need to display these orders. All right, so now I'll just close this terminal. I'll restart the application. And before I forget here, I'm going to use address as a correct address. So that will be context dot, watch passing the user provider and use dot user address. Great. Now also remove this address to be used. We don't need that anymore. We are pretty sure of the value that we have now in the on apple pay result, which you're going to copy in on Google pay result. Both are going to have the same thing. You, we are going check. If provider dot of user provider Context, user address is empty. So if the user's address is empty, then we want to make sure that we store that address. So for example, if we go where, and now we don't have that box. So now if we enter in all the, uh, addresses and click on, buy with pay, and then click on, buy with pay, then we want that this address gets stored. We don't want to formally ask the user to, you know, uh, enter the address separately. So you're exactly what we're doing. So now we will create a services called address services.dot file. And also we are going to have a small.dot after that. We are going to com copy most of the things from admin services. So let's quickly copy that, paste it over here. Let's remove unnecessary stuff here. We are not going to require any of this, even any of this. And now in the address services, first thing that we need to create is save user address. This will only require the user's address and will be from the user provider. So we need that after that, we need to use jtp.post called API slash save user address. After that we need to pass in the headers and the body will be Jason encoded, And we need to pass in the address to the server side. So we have this address. Great. Now we just need to error handle this error. And after this is success, we don't need to show a snack bar, but we need to store this address in the user provider. So we will have user provider dot user dot copy with, and then use the address. So now we will just decode this and have response dot body pass in the address exactly what we've done multiple times before and here, this will return to us a user model. So let's import that user model. And now we need to set this user provider using the model. So we have user provider got set user from model passing the user model. Great. We have that created and the data on the user address is being updated. Now we can come in the address screen, create final address services, and we have not called this address services address, change of name of the file. Also remove these unused imports and let's call this address services. Copy this class, paste it over here, call this address services equal to address services, Copy this address services. And in the, if condition itself, we're going to save the address. And the address here is going to be address to be used, make sure to not enter provider of user provider user address that will store in the providers user address and not the address from the form. If the user enters one after this, we just need to save that data. Also, we need to create the save user address API. So let's quickly create both of the APIs together. So the first one is going to be your exercise. So in the user dot JS file, what I want you to do is create a post request to save the user address. All right, that's your task. You can go ahead anywhere, how whatever you want to do with it. I highly recommend you to do this exercise so that you get to know how much you're understanding. If you're not. Then later on while we perform other exercises, you can just know if you're understanding or not, and then learn from it again. Were you able to do it? I ideally hope you were able to do it. That would be really great to know in the comment section. So we have slash API slash save user slash hyphen address. Then we want then a sync request response, and then we are going to have a try and a catch block, and we're going have re status 500 Jason as the error with E dot message. After that in the tri block, we want to get the user's address. So we have constant address equal to request body.After that, we want to find the user so that we can store in the user's address, property, this user. So we have eight user it, user dot, find by ID and find it using request dot user. After that, we can use user dot address, which is a property on user equal to the address we receive from the request dot body. And after that, we just need to save it. Don't forget to save it. Otherwise it won't reflect in the database, even though it will change for some time, you know, because in the client side, the unsuccessful person, but over year when we restart the application, it won't be saved because in the database it does not save. And then we need to make sure that we send the user back. And over here, we are just using that address part of the user to change it. Great. After that, we, I promised you without testing, we are going to move on to ordering product so that we have some self-confidence in ourself. It's really bad. I know, but let's try to do it since you're doing it for fun right now. So yeah, we are going to have something similar, a post request to order a product. And we are going to call this basically simply order. And from here, we are going to get the card. So the entire card that the user is ordering, then the total price, and then the address of the user, so that we get to know where we are delivering right now. We don't need the user part of AR. So let's quickly remove all of that stuff and now create a model for order. So we have order dot JS. Let's quickly create the order. So we have constant Mongo, which is equal to require Mongo. And then we require, well order schema, which will be equal to Mongo. Schema also create an order out of this, which will be a model. So we are Mongo dot model and we will call this order and pass in the order. Schema also make sure to model export this order model. And I don't think anywhere we will be needing this order schema thing. Great. So now we want this mongoose dot schema. Now, how is our order schema going to look like now? I would like to give you this as an exercise as well, just brainstorm and think what all things are required and what are the types going to be in this order. Schema. Don't worry if it's different from mine later on, but just try it on your own. And if both of them match according to you and you think you'll be able to convert the code ahead, I would, I would really appreciate that. And please go ahead and try that on your own. Were you able to do it? So now we are going to have products as an a and your first of all, we are going to have product, which will be the product schema. After that, we need a quantity. So we have quantity as a type of number and it is required. This is simply similar to the cart that we have because cart is going to store the products. Then we have total price and total price we already saw is of the type number. And it is required as well after that we have address. So we want that. So we have type string required set to two. After that we have user ID and then we want that to be required as well. User ID will basically store who ordered this right after that this will be of the type string then ordered at. So the time it was ordered at, so it'll be of the type number we are basically going to convert everything and date, time to the number, which will be milliseconds since epoch, which will be from the date milliseconds since, you know, January 1st, 1970, and then required set to true. Everything is required except this last part, which is the status. So what is the status of my order? It is going to be of the type number and will be default to zero visors of the type number. Well, it's mainly because zero is pending. That means that the user is just ordered. One will mean completed. Two will mean received and three will mean delivered. So zero pending means that the user has just com placed the order completed will mean that the user or our product has been delivered from our side received means that the user has tick marked it and delivered means, yeah, both the parties have agreed and all is done. So now we can come to this order. And in this order, what do we need to do? Well, first of all, create a products, temporary variable at the top, which will be an empty a here we will have four, let I is equal to zero. I is less than card length I plus plus, so the card is going to be again in adjacent format. We're going to convert it to Jason because we can't give, you know, like a model to our server. Now we want to find that particular product from which we are converting to the product, you know, from Mongo. So we have let product equal to a weight eight product find by ID pass in the IDs card. I product dot underscore ID. Then why are we getting this product? Now, we just need to check if the quantity is greater than the quantity that we are asked. So if we have the very first product, let's say iPhone, we are, we order 20 product, 20 quantities of it. And that much don't exist only. What do we do? So we are just checking over if product dot quantity, if it's greater than or equal to cart quantity, that means that the quantity that the admin has decided is greater than what the user is ordering. Then the order will be successful. So we want product dot quantity minus equal to card. I quantity. Then we will just use products, which is this temporary a that we created dot push, because we now need to push to this I, this product, the quantity, which will be card at I quantity. That means that the order is being placed. So we are just setting up the order products. And now we will just say away product.save. And we are using this <inaudible> product.save in the loop itself so that the, because the products are going to keep changing, right? So we just need to save it as soon as the product is your and the product is accessed using this I variable, which is in the, for loop. After that, we are going to have this L condition saying return, re Jason with a message saying with the back sticks. I've already mentioned what this back tick are. Uh, it'll allow us fostering interpolation, which will be product.name is out of stock. And also this will change the status code, which will be 400 called bad request. So as do state is 400. Jason product is out of stock. After that is done, we need to make sure that the cart is empty. So we are now finding the user using that user ID. After that, we are making sure that the user dot card is set to empty list. And then we are just using user is equal to avoid user.save. Now we need to create a new order. So we have let order equal to new order. Then we pass in the particular thing. So that is the first thing that we need. Well, let's see. Oops, I went too far ahead. So we need products, total price address, user ID ordered at, let's see if I remember them. So we have products, total price, address, user ID, and now the user ID, you can see, we can't pass it in like this because the user ID is request dot user. All of these had the same name, same key and same value, but user ID has a bit of different and let's see what else is there. And we have status as well and ordered at. So we have ordered at new date dot, get time, get milliseconds, whatever you want, which is going to store it in milliseconds. You can see gets the milliseconds of a date using local time. Great, great, great. And if you use get time, you can see it will get us the time value in milliseconds. So I think I'm going to use it the get time. And then I will use order is equal to ate order, save and rest dot Jason, the order, because we don't really care about the user. Now user will save. And when this says success, we will make sure that their cart is also empty. So now let's go back to address services. AndInstead of fetching all the products, we are going to place the order. So let's change this to void place order. We are going to receive a build context. So let's quickly add this required build context, then required string address. And then we required the total sum that we have after that let's remove this product list. And now we are going to have slash admin. Nope, we have slash API slash order. This is a simplest URL that we have created. So I remember it and we don't need get, we need post after that. We need a body which will be Jason encode, and then we need to pass in certain things. Well, first of all is cart. So we have user provider dot item dot user dot cart, and this is already adjacent format or in a list format. We don't need to worry about it. And you have address as address and total price. Let's convert it to a string. Total price is total sum. If we go to our user dos, we have card, total price and address. We have total price pass in away. Great. After this, we need to error handling. So yeah, we just need to make sure that the card is empty. And we also tell the user that your product has been, Or your order has been placed. So let me remove the return product list because this is wide. And here, first of all, we will have user user equal to user provider dot user dot copy with, and we have a copy with card as an empty list. Now we will do user provider dot set user from model pass in the correct user. And you have it also let's show a snack bar saying that the order has been place. So we will say your order has been placed, saving this much, and let's restart our application. Also in the address screen, let's bind it all together. Finally. So we have an address services.place, order passing the context. Then the address will be addressed to be used. And the total sum is going to be widget total amount to string to fix this error. Well, we have converted it to string and the reason we converted it to string was actually, if we see this widget total amount is of the type Double. So we just need to convert it to a double. So we will have double dot pass pass in the widget total amount, and this will convert it to a double format. Great. Also, let's copy this and paste it down in case it doesn't work, then we can obviously change it later on. All of these functions are bound to each other, so let's quickly see and wish our app is now successful. Also let us just proceed to buy two items. So I'm going to enter one zero one wall street, call this area, what do I call this? Now? Let's say one zero, one fake building. Then this will be called wall street. This will be the pin code. So let's say 1 0, 0, 0 1. And the town or city, let's say washing 10, I'll click on buy with apple pay and close. This nothing shows up. Nothing is done. So now I can click on done and pay with the passcode. And that part is done. Nothing really shows up. I noticed some kind of error. You can see in this on Google pay result. We've not set, listen to false. And even your, uh, if you go to the on apple pay, we've not set. Listen to false. Now let's try to run our application. So if I click on, well, again, enter some useless information. We are going to call the street one zero, zero one, and the town as Washington. Then we can click on buy and then click on pay with passcode. You can see your order has been placed. This address is showing up. That's a very good sign. And if you go back, the cart is cleared off and now everywhere our address is being seen. So now, if I restart the application, you can see this address is showing up. Even if I refresh the browser where we can see in the orders, a new order is placed with a total price of 2008 ordered at these many milliseconds.The status right now is zero, and this is the address where we want to deliver it. Great. So now the next thing is OER quickly. Let's display the orders that we have and when we click on them, we want to display the orders details. All right. So now I will just close all the other tabs again and here in the account details. So let's go to the account part. And in the screens part, let's go to the account screen. And here we have the orders. Now in the orders, we need to display stuff. So here we have the order screen, instead of displaying the static images, we need to display our orders. Now that should be very easy to do so you are in the account. We are going to create a new folder called services at account services. And let's give this as an exercise that we need to fetch all the orders of the particular user. So try it on your own and not even giving hints for this one. So go ahead, pause the video and do it on your own. Were you able to do it, if not, let's do it and make sure that you understand the logic behind this. If not, you can ask me in the comment section below. So yeah, we are just going to have a get request because we need to fetch all the orders, right? So I'm just going to go ahead and copy some stuff from home services and it'll be a list of products. So I'm gonna copy this one because we are going to get all the products of the user. I mean, all the orders of the user. So here we can just name this as which my orders. Then we require the build context. Then the provider, then user provider, all of that stuff, then import HTTP as HTTP. After that, we need to do error handling and then theri should be imported from global variables. And then the Jason decode thing. And I think we'll have to remove this. And instead I had our own, uh, instead of product, we will need, uh, order from Jason and we'll have to create that model, but we'll create that after creating the API for our orders. So here, the API is going to change with API slash orders slash me. So it'll get all the orders of the user and we don't need to pass in the UID of the user because well, we have it in request user. So now we will go to user dot JS because it's a user route. We want the user orders. So yeah, we are going to have user router dot get slash API slash orders slash me and pass in oath, middleware and have asynchronous request response, and then use, try and catch block to catch any errors. And then just send in any error with a status quo of five and the name error with E dot message. After that, we can just come away and, uh, let orders equal to innovate order dot, find pass in the required user ID and pass in request dot user, which will be the user's ID. And after that, we will just send in this order also let's put cons to where, because we're doing nothing else. So we are basically finding all the orders with this user's ID. And the user ID is with the request dot user. Now we should be able to get hold of this. So let's go to the account services. And in your first of all, we need to create a model for the user, uh, for order. So let's quickly go down and create order or dart file. Let's create an order class and define some properties of this order.Class is going have a string of ID, then a list of products, which we are going to change. So whatever product that we get, we need to convert that into a product model as well. After that, we need a list of NGER of quantity. So every product that we are going to store later on will have its own quantity. Now, instead of storing it in a map, we are storing it as two different list. I think it's a better way of doing it because whenever, uh, ahead, when we see, when we create the two map and from map functions, you'll see that this products will get access to only the product, because this is a list of product. And here we also need the quantity, right? So we are creating a separate property for it. Then we need a string address, then the string user ID, then the timestamp.So let's see what we call as a timestamp in our order GS model. So it is called ordered at, so let's copy this and call this ordered at, then we need final end status, and then we need to generate a construction for this. After that, we need to create, create Jason serialization. And here, the two map is fine, but from map, we need to make some changes. You can see it takes in list of product from map of products. And then we are mapping through each and every one to get product from map X. So here, when we map through the products, we have both another map in that product and quantity. You remember that? So if you come aware, you can see this is the products added that it is counting. So we have map our products, it's mapping through everything and then creating a product from that mapped product. So we have access to only one product. So we have access to this whole object away. So it's creating the product from this whole object and this whole object consists of product and quantity, both. So it'll give us an error. It'll give us Nu whatever that we have, because we can't create a product from map of an object, right? So here we need to pass in product. And the same thing for quantity. We, your, we are list of end from map of products. Well, first of all, and then we need to map through all of them. So we have get, we get access to X and then we will have X at quantity as a returning value. So we map through the products and then we have X dot, uh, X quantity return. This should be great for us. Also, the ID should be map underscore ID, make sure to make that change because here the ID is underscore ID. After that, we can go to the account services and instead of having product list, name, we are gonna change it. So I'm pressing option on Mac just to grab each and everything, your, and then convert this to well order list. And here it didn't get selected. So let me remove this. And here we have it order list, and it will be a list of orders. So you are also, we are gonna have a list of order and you are going to con have order from Jason. And then all the logic that we have, this will convert it to Jason. This will convert string to convert Jason, to string. And then this will convert this to our order modelAnd then return it. Then we need to go in the orders and create and remove this temporary list that we add. And instead of that, we are going to have list of orders, which will be called orders. Let's import order. Now we will create init state remove the implement init state functionality thing. Then you, we are going have fetch orders, take this fetch orders, create avoid function for it, call it asynchronous. And now also initialize account services. We are already familiar with all of that stuff again and again, we are doing this. I hope it's gonna practice. Now we will have account services equal to account services. Now we can take this account services, set it to orders, and this will be equal to innovate account services dot switch my orders. We will pass in the build context and it doesn't require any category. So we need to go to our function and update it. So let's go to our function, remove this category thing. Also remove this product dot, do no necessary imports and then call set state. So that function rebuilds, and here we will check. If order is equal, equal to Nu, then show a constant loader. Otherwise a columnAlso, let's go down here and instead of item, count as list.link, you're going to have orders.link. And even here, the image is going to be orders at particular index products at zero images at not index, but zero. So here, what we're doing is grabbing one particular order because we are in a list view builder. So we are grabbing one particular order. It's products and products can be an a, so we're grabbing the very first elementOr the very first product, and then showing it's very first image. Now, if we save this much, let's see what we get. We are getting a loading indicator. That seems to be good. Let's see, in the DVA, what we get when we click away, we have our orders showing up. Now the next thing is, whenever we click on this, we need to go to the order detail screen. And she see the details of this order. This should be very easy to do so let's implement it quickly. All right, so now let's close all the safe files, even the terminal. And in here, we are gonna create another feature called order details and then create a screen for that called order detail screen. So let's create it. Now, this order detail screen is going to be repeated throughout our application now. So even the admin screen, we're going to use it. So that's pretty cool. Now we don't wanna create a stateful budget out of this, and we will call this order details screen. And also here, we need to get access to the order because we need to display an order based on what order we get, right? Just like the single product widget that we created. So here we have required this dot order. Also create a route name for this. So we have static, constant string, route name, equal to slash order details. Now, after this, we can take this route name, go to the router.dot and pass it in. So we have order details, screen, route name. So let's remove this extra route name and here, whatever we get should be treated as an order. And your, we will call this order. Also, let's take this, pass it in away and pass in the order detail screen. After that, we also need an order. Great. So after having this much, we need to create the UI offer application. Now, how do we go about it? Well, first of all, convert this in a scaffold and here we see the very first thing is an app bar. So we'll go to the home screen, copy this entire app bar and paste it over here. Now, obviously we will also need the navigate to search screen thing. So we will paste that also at also then we also need to import global variables, import search screen, and great. We have this. Now let's save this much, go to our orders dot file. And you are, you're going to wrap this single product with a gesture detector. Again. Now this gesture detector will help us navigate to this particular order detail screen. So you have navigator dot push namedPass in the route name, which will be order Detail, screen, route name pass in the arguments, which will be orders, add particular index so that we pass in one particular order. And this will fetch us from the list, a particular order. Now we can come back to orders, detail screen, and if we click, we get navigated. Great. Now the very first thing that we need to see is this text and this box with order date, order ID, and order total let's quickly set it up. So we have a body where we are going to have a single child scroll view, obviously, because this has a very great chance of scrolling. Then we have a child and then a column and column has many children. So the first child is going to be the text that just says view order details. So we have constant text view order, uh, I think, yeah, then we need to pass in style, which will be textile of font size 22 and font, weight, or font, weight bull. After that, we can just see what we are getting looking great. Then we just need to wrap it with a container so that we can show this box with some border. So we'll wrap it with a container with a child as a column of these texts. And this container will have some border like this. So obviously we are going to app it with a container. Then we need to pass in a decoration so that we can have a border. So it'll be box decoration and box decoration will have border as border dot, allColor as colors.black twelves. After that, we are going to have the child as a column of all these texts so we can pass it in. So we have children and the very first text that we have is order date. So we have order date as widget order created at or ordered at let's see ordered at. And then I think this much is enough. So let's quickly save this and see what we are getting. All right, order data showing up. This is correct, but we need to format this so we can just see if so to format this. Well, we have to use another dependency called Intel. You should be very familiar with this because it's a very great date format for us. So we are gonna stop our app execution. And now,Even though it's looking great while there are certain changes, UNC, that it's very stick to the left side. So let's add a padding to this entire column and wrap this with a padding. This is called refactoring, and now we're not able to see the changes, but there would be something, all right, let's run without debugging and see what we're getting. All right. So wraps load it up. I'll cancel the Debu console. And here I'll go to the, my orders and you can see some padding has been created, but now we can also use Intel. So now we can update format and let's see why we are not getting anything. So we need to import Intel. So yeah, I have imported it at the top. So I'll do date format dot and you can see it gives us all the methods, but we are going to use its object to format it. And here we need to pass in a date. So yeah, now we need to pass in the date time. So now to create date, time from milliseconds, we can use datetime dot from millisecond since epoch and epoch refers to VJA milliseconds, micro, not microseconds milliseconds from milliseconds. Let's quickly format this Millisecond since Och and now Och refers to January 1st, 1970. So we just need to pass in the milliseconds that have passed from then, and this will convert it to daytime and we are passing it in. Let's see what we are getting. So here we are made 13 20, 22, 1 10 54 air. That looks great. So after this, well, first of all, let's design the container. It's not taking the entire available space. So what we can pass into this container is padding, no, sorry, width of double infinity. And it'll take in all the available space. And now we need to make sure that there's some bit of PAing your inside as well. So we have constant sets dot all 10, and now this looks good. Also, this, all of this came in center. So the column should be having cross access alignment of cross access, alignment dot start. And you, we have, it looks great after that, even this column, the necessary column that we have should have the same property so that this comes away cool. After this, we need order ID. So let's quickly create a text saying order ID and pass in the order ID, which will be widget.order.id. And we are going to have order total, which will be widget order, total price. So let's quickly go to the order model and we forgotten to add the property of final, double, total price. Let's receive it through the, through the constructor. Now we will have total price pass in the total price. Then we are going to pass in total price over here, which will be map at total price. And we convert it to double and check. If it's Nu, then we want to pass in 0.0. Otherwise the map, total map, total price. Then we come back over here and pass in map.order.total price. And for now it'll not show anything. Yep. We need to reload it. So let's quickly come over, click on order. And yeah, we have it order total of 2008. So obviously we need to add a dollar sign. So we pass in slash dollar. Great. So we have order total showing up as that. Now let's align all of these three together. Like we have over here. So let's just space it out, the least effort, the way we can do it. So I think this much seems to be enough, so let's space it out even more and save it.Yep. Let's base it out even more and even your more, yep. This looks good to me. So if you have any changes, you can just make it, let's shift this a bit away actually once face away. Yep. We, this looks good. Now after this, we need the purchase details, which will show all the products with that quantity. So we have constant after this container, we have, we are going have constant size box of height 10, and then we have a constant text of purchase details. So we can just copy this text, paste it over here and have purchase details and save it. You, we have it resort after this. We will obviously create a container and then pass it in over here. And we need the same border and the width will be same. We need a bit of padding as well, but I don't think we need to specify any of those properties. So in the child government to have a column, which will have a main access alignment of main access alignment got start so that the column doesn't start from the middle, right? And now in the children, we have to remove all of these texts because we don't have them. And now what do we need to do? Well, we have multiple products in that because we have a products. I, so we need to run a four loop displaying each and every product. So we have four entire equal to zero. I is less than widget.order.products.link. I plus, plus Then we are going to return a row which will have children. And the first child is going to be image.network of widget dot order dot products@i.total.total, because we don't want to show the price. We need to show the image. And we are going to show the very first image as the cover image. Let's see what we're getting. Yeah, we are getting it correctly. So yeah, we are just going to reduce the height. So we have height as one 20. The width has one 20 and save it. Yep. Now, now this is looking better. Now we are going to have some spacing left and then we will leave a size box of width five, and then we want to enter the products name. And since this is in row, we can use for loop again and again, over here and make sure to not add something like this, because these are collections in flutter. They don't allow to add this braces and you can only do it for one particular widget. So after this, we need expanded and expanded is going to have a child which will be column, which will have children. And the first child is going to be the product's name. So let's quickly create that text. So we have text widget dot order dot products@i.name And then get the style. So we have constant textile as font, size 17 and font weight. So we have font ways, weight as font, weight dot bowl. After that let's come over. Yeah, we have it also let's put the cross access alignment as cross access alignment dot start suite. Now we just need a quantity. So we will pass in the required quantity, which will be Again, another text. And we will remove all the styling. We don't need any of that styling and we'll just pass in quantity and we are not getting access to this products. Quantity. If we get access to this products dot quantity, it'll give us the quantity of the number of products that are left. So here we need to get the orders, quantity, not the product, that individual products quantity. So we have widget dot order dot quantity. I two string. So with this, we get the order and we have the list of integer of quantity so that we get every product's quantity as it is. And if you save this much, we have two selects quickly pass in, pass it in as a string, which will be quantity, passing dollar sign and use string interpolation. Now we don't need that two string method away anymore. And now we have it look school. Now let's just make some changes in this text. So we have max lines as two and overflow as text overflow dot SIS. And that's why we have wrapped this entire column with an expanded widget so that the text can overflow to max two lines. Otherwise it'll just start showing.dot do over here. Great. Having the purchase details set up. Now, the next thing is to show these tracking. So what we going to do is copy the size box and this constant text past it in, after this container and here we are going have tracking and past it in. Now we can see tracking again. We are going to have a container, but in that container, we are going to have a new widget, which I'm not sure if you've seen it before, but it's pretty interesting. So we have it now instead of returning this entire column or so instead of returning this entire column, what we are going to do is from your, we are going to have a widget known as tepo. So with this step, it'll allow us to make something like this pretty easily. You'll see that. So the, uh, required arguments will pass in steps. So let's define the steps that we have. Well, the first step is the pending step. So created. So we need a title which will be a constant text saying pending. Then we need a content which will be a constant text saying your order is yet to be delivered and then pass the trailing comas. Yep. Now let's see how it's looking. This looks good. And we look into these action buttons later on because these actions buttons should only be available to the admin, not to the user, but we look into that in some time. So after the steps, we need two more steps. So we have one more after this and one more and actually one more. So this was the pending text. Now we need to pass in completed text. And here it'll say that your order has been delivered. You are yet to sign and what signing. I mean, just the document or whatever. It asks us to sign, to verify that we have completed the thing. Then we need to pass and received. And here it'll be, your order has been delivered and signed by you. And finally it's called delivered. And this delivered is again gonna be of the same text, but it will not be visible at all. And it'll just say that, yeah, your order has been delivered and signed by you, but it's just telling that both the parties have agreed to it and you have it. You can see this looks cool already. Now let's remove these action buttons. So we can come down at the top in the stepper, we are going to define controls builder with this controls builder builder. You can define what the controls are going to show up. Well, we are going to, first of all, return context and details.So context is the bill context and details will tell us the current extent that we are on and all of that thing. So yeah, we are just going to return a constant sized box because we don't want to see anything at all. So you can see nothing shows up and now we need this highlighting to be done, right? If we have pen, the order has been completed, then we want to see completed pending and all of that task. So that highlighting has to be done. So for that, we are going to go on the top and create a global variable called current step. Let me quickly have current step, and this will be equal to zero initially. And this is why we have sta so we have made sure that the status here is zero because in the stepper we have to pass in the integer value. So having anything else like received or some text away would be very difficult to convert again and again, and would introduce chances of bugs. So now let's create an N stage function and here we will have current step equal to widget order dot status. And now we will use this current step as the current step for our stepper widget. So if we go to the stepper, we are going to have current step passed in as the current step, save this much. Now, if active is going to be well, a bullion value saying if the current step is greater than zero or not. So if the current step is greater than zero, that means that it is active. And yeah, the current step is not greater than zero. It is equal to zero. So just to demonstrate, if we put in equal to, you can see this is highlighted. So we are gonna have something similar over here. So let's quickly pass that we will pass in one over here, two over here, and then this will be greater than or equal to three. So if by chance we become three or greater than three, it's not possible just for error purposes, we can handle this over you. And now we have everything set up. So now last thing is if that part is completed. So if you saw, even if it is completed, it's showing it's highlighting it. So let me just quickly show it to you. If I put equal to where and come back, you can see, even though it is completed, it's showing one. I don't want to show one. I want to show a tick mark sign. So what I can do is first of all, remove this equal to sign and pass in state. So state will define how our step state is going to look like. So if current step is greater than zero, then I wanna make sure that the step state is complete, which is that tick mark sign, otherwise step state dot indexed. That means the numbering part, which is by default. If you hover over this, you can see it is step state index.Now we're gonna copy this for straight away, pass one, pass in two, and your passing greater than or equal two, three. So having this stepper widget and all of the order details created, let's jump into the admin side of things. All right. So now let's again close, all close, all the safe files and all the features, because now we are gonna jump in the admin side of things and we are rarely going to use anything now from these screens. I mean, we are going to reuse widgets, but not any screen as such. So yeah, we are going to create a new screen called orders, underscore screen dot, and it's going be very similar to post screen. So let's quickly. So yeah, we are gonna import material dot, create a state full widget call this orders screen, and this will show us all the orders that are there. So we are going have a scaffold, actually not a scaffold because I wanna show you, or actually let's just first change the user's type so that we get to the admin side of things. So I think the email over here was this, so I can type the admin. And now if I just return a container for now and restart the app, we see the admin. So here we want to see the orders page, not the card page, but all the orders. So for that, we are going to return a grid view builder because we are already having a scaffold away and then we need to pass in the item count, and now we need to create an API for that. So let's quickly create that in the admin services.dot file. Let's minimize all of this account features and go to admin services, dot dot five, remove dot FFI. We imported that by mistake and go down and we need to fetch the list of orders. So what I can do is copy this and paste it over here, call this fetch all orders and similar to the product API. We're going to have that. So let's take it as an exercise. Please do it on your own. And let me know if you could do it all right. So now what we need to do is have user provider, and this will be a list of orders. Also, we are going to return a list of order, and now we are going to use this admin thing and get the orders, not products. Then we are gonna pass in the token and then we are going to handle the error. And in the, on success, we are going to have order dots from Jason, remove on from Jason. And even here, we will name this as an order list. So let me quickly grab all three of them and pass in order and person or the list. Pretty familiar with that. Aren't we, we can just copy this and we'll use it, but for that, we need to create an API. So let's go to the admin JS part and get all the things. So create a route and pause the video, create a route and let me know if you could do it. All right. So vLab admin router dot get slash admin slash get orders, passing the admin middleware, then asynchronous request response. Then we have a try and catch block. Mary, we are going to have rest Jason at 500 and restaurant state, sorry, 500 Jason error and E message. Then we need to get all the orders. That should be like the products part. You can see we have this. So it's very going to be very similar. We just need to replace the variable name and the product model name. So we have a eight order dot fine, and we need to import this order So we can come aware and have constant order equal to require Slash slash middle middleware model slash order. And then over here, we just need to return rest Jason at all the orders. And we have the route created. Now, if we come aware and create the in state function, then the list of the products part, I hope you add, uh, stop the video and tried it on your own. It's very, very similar to what we have done. It's just using some logic to make difference. And we also create admin services, admin services equal to this admin services. After that, we are going to take this. So also call fetch orders function, create this as an asynchronous function, take this fetch orders, paste it in over year. And then we have admin services dot fetch, all orders pass in the context and there we have it. Also, we need to make sure that we store it in the orders variable because that's what it's going to return. Is it, uh, return it to us. And that's why we have made this as an asynchronous function. Let's mention the function type. Great. So now we need to pass in the item count, which will be orders.link. Then we need to pass in the item builder. And here we are going to get context and index, and we are going to have final order data equal to orders At that particular index. So it'll give us one particular order, which we are going to use. So we are going to have a return property, which will be size box so that we constrain it to a particular height. And we have height as one 40 and the child as a single product. We already remember that now we are using the same widget that we created for displaying order as well. And we are just taking in an image. So yeah, the image is going to be ordered data dot products, and we are going to grab the very first product and its very first image because product is a list. So we have products at zero images at zero and yep. Now we need to pass in the grid delegate. So let's pass in grid delegate. Now what do we want? Well, the grid delegate should have something like, you know, both the sides, only two products should fill in in the horizontal direction. So we have constant sliver grid delegate with fixed cross access count plus and two. And yeah, let's bind this order screen to our admin screen, which will consist of the bottom nav bar. So are instead of showing cartage, we are gonna show orders, screen passing the constant array. Also in this order screen, we are going to check if orders is equal to Nu, otherwise it'll give us an error. So if orders is equal to the Nu, then we wanna show a loader. Otherwise a grid view builder. Now let's see diva, no error still. Now let's restart our application. Yeah, the products and yeah, we are not seeing any product because you have not called set state. So let's quickly call the set state function and you can see if we don't call it, the builder's not rebuilding only. Right. That's right. And here we have the order shown again. Let's restart. See the console come back and yeah. Yeah. Now whenever we click on this, we need to go to the order detail screen so that the admin can mark as completed or not. So what we can have is over here, the size box should be wrapped with the gesture detector pass in the on tap as navigator push named, pass in the route name, which will be order details, screen, route name, pass in the argument and it'll be order data. Great. Now, if I click over here, we get to the order, the task screen. Now we need to be able to make sure that we can make some changes, aware. We talked about, you know, having the buttons aware so that we can mark them as spending completed or received. So let's quickly create them. So here our Order detail screen itself, let's go down to the stepper widget. I've used control F to find a particular widget away and we have the stepper widget here. We have the controls builder. Now what we need to check in this controls builder, if the user's type is adamant or not. So again, we will go up here and actually in the be function called final user is equal to provider.off user provider context. And we will also use user. I don't think we need to use user provider to store any user data. So you, in the step of widget we have, if user dot type is equal, equal to admin. So if it's an admin, then we need to show a custom button telling them if it's done, then click on done so that we can come to the next step. So we have return custom button saying done and on, on tap, we need to be able to change the order status. So let's create an API for that. But for now we are going to keep the on tap. Let's keep it with an error so that we can come back here very soon. So we are going to do this in the element services. So I'm just going to copy one of this function. So, yep. And this should be fairly easy for you two. So pause the video, go ahead. Do it. There's no harm in doing it.So now in the world we have change orders, status, Accept the build context and require end status. So we need to get the status of the product that we have so that we can increase it by one or otherwise. We are just going to pass in the change order status from there and increment the status by one so that we can set the status to a new value and we don't need on success anymore. I mean, we need it, but we also need an order value. So we have required order order with this order. We get access to the order ID and on success so that we can, you know, update the thing real time. So if we click on done, it'll be done in the database, but it'll not refresh. So we need to make sure we call search date and increment the value by one. So here we have user provider. After that, We need a response and here we need to pass in the ID, which will be order ID. And then the on success should be on success. You can do it this way or you can just pass in on success a way like this. Both of them are completely fine and we are now return types. So we are not returning anything. So now, uh, let's quickly create this post request. So I'll name this change order status and quickly copy this, go to admin or JS and create a post route. So let's just copy this, paste it away and call this well, let's copy it again and past it away. So yeah, we have access to the ID. So that is the ID. And other than that, I think we also need access to the status, right? I mean, we are sending the orders ID, but we also need to send the updated status. So we have status and pass in the status. Otherwise, what you could have done is incremented the value there itself by getting the previous over year itself, by getting the previous value of the status and incrementing it by one, it would be the same thing, but I think we can pass in the status, right? So here we are going to get order ID and status. Then we are going to find the particular ID by using of eight order find by ID. We don't need to delete anything. So we just need to find by I ID and after getting that ID, we need to update it status. So we have order status equal to the status. As I said, if you want, you can just use order status plus equals one. And that is completely fine too. I think this one and that one is only the same thing itself after that we just need to do order is equal to eight order.save and then return the order. All right, let's come back over here. And in the on tap, we are going to create a function at the top called change order details. So avoid change order status, and let's create a comment over saying only for admin and like this <laugh>. Yep. So that it grabs attention. You know, otherwise user will get confused. You know, why are we using this function in order details, which will only be for the user side. We never said it's going to be for the user side. Great. So now we need to have final admin services created the instance of this class. And then we are going to take this admin services change or status pass the context and the updated status. So the updated status is whatever status is right now. Plus one, how do we get the current? Well, we can ask her over year. Otherwise we can just use current step plus one, or both of them are the same thing. And now passing the order and the order is going to be widget dot order and in on success, what are we going to do? Well, this is going to be interesting. So in the, on success, whenever there's on success, then we need to make sure that the current step increases by one. So what we need to do is set state current step plus equal to one. And that's it that makes our app look real time. Now in the on tap, we just need to pass in this change order status and then pass in the status. Now here we could have passed in current step, but you know, we could have done that over there as well because current step is a global variable here. I'm gonna make use of this details property that the stepper widget only gives us to find the current step that is there. So whenever we click on this done button, it'll take that current step and increment it by one, which the details builder will give us, you know, so yeah, you can see, we have the button done button and if I click on it, it's completed. And if I go to the user side of the application, so let me quickly make this as a user and update itAnd then restart the application here. If I go to the product details, you can see it is spending, but we are not getting the option to edit. And it has made this as a tick mark, you can try it on your own. So we have that completed. Now we are able to change the order status. Now the final thing that we need to work on is showing the user, the graph based on the category and also the total earnings still now. All right, so now let's create a new route for it. We are not starting with the screen UI because this is going to take some time the earnings part. So let's quickly create admin router dot get, because now we don't wanna post anything. We just need to get the total earnings that we have had till now. So we slash admin slash analytics pass in the admin middleware and then have asynchronous request response and then have a try and a catch block.So now we will take this risk and pass it in over here. Now we need to get the total earnings. First of all, now to get the earnings. First of all, we need the orders. So let's get all the orders and have of eight order dot find and not promise provider order. So yeah, order dot find and pass it in with an Mt basis so that we get all the orders now to get the total earnings, we just need to create a global variable or a local variable in the function, total earnings, and well, what do we need to do? Well, let's look at the orders collection just so we know what we are doing. So here we need to go through every product that is there in order, and we need to go through every order. So suppose have another order like this. You can presume I have. So we need to go through every order. And in every pro order, we need to go through every product that is there and add their total earnings to this total earnings variable. So how are we going to implement that? Well, for let I is equal to zero, I is less than orders length. So where we are going to have one and then increment the I value, then we are going to have another for loop so that we go through every orders, products value. So we have four. Let the for let J is equal to zero. J is less than orders dot length, J plus plus. And now what we need to do is add the total earning with every orders, products that is there, and this will not be orders dot length, you know, because here we are already in the orders list. So we went through every list and now we need to go through every product that is there. So here we will have orders at I, which will Fe us that particular order dot products dot length, which is this I, so that we go through every product in this. I, now we can take this products. So we have orders at I products, which will give us the particular orders, products I, and we need to fetch that particular product. So we have at J and then to get the total earning, what we need to do is multiply this quantity with this product's price, right? So we have quantity, which is one and two 10. So we have 30. So we need to do exactly that. So we have J quantity and we can copy this whole thing again and have products at J product. You can see where we have product away. And then we need to pass in dot price. So we have dot price. So after this, we have access to the total earnings, but that's not it. We also need to get the category vice products so that we can show it in the graph. So here we are going to create a new function for it together. And we are going to call this function Fe category vice products, and here get the category. And we don't need to mention the type of error because as I told JavaScript is a dynamically type language. And now to make this function asynchronous, we can pass an asynchronous over year. Otherwise we could have created function like this, which will be constant fit category, product equal to this and pass in an arrow function like this and call this asynchronous like we've created callback functions multiple times, but let's try an alternative syntax right now. So yes, Aing function. And we have the category now as well. So we need to find the category orders. So we will have let category orders equal to ate order dot find. And now what do we need to find? We need to find the orders of that particular category. So let me minimize this. So we need to find orders in every product to check if their product aware is having the category of the category that is mentioned away. So for that, we are going to pass in a string. Every time we did a category like this, for suppose, if we have a way product fine, then we need to, to pass in category like this. But for order, we need cat products, which is this the main area inside of that product, which is this one area, which we can call products. So we have this particular product and we need to find its category. So we have dot category and you can see the error already showing up. We can't use anything like this, so we need to convert it to a string and then match it. So we need to match it with the category and boom, we have all the category orders. Now, now similar to this part, we need to loop through all the products so that we can get their total earnings. Also, we need to create a variable called let earnings equal to zero. We will take this earnings and replace total earnings with this earnings and use category orders anywhere we see orders. So we have category orders, category orders, category orders, and even your category orders. And finally, after that, we need to return earnings. All right, now we can take this fetch category wise product and use that. And we need to use this five more times, right? We have five categories created, so to get category wise. So let's type it here. Category wise, order fetching. Now we can just do eight fetch category, vice product and pass in mobiles as the very first category. I hope that is what we named it. If we go back to our global variables here, we can see we have mobiles essentials appliances. So we just need to copy names from your, And then we are going to save it in our mobile earnings variable so that we can send it to our client side. And we are going to paste it four more times. Let's remove one more time. And now we have essentials. So let's paste it AER. Then we have appliances let's past that after that books and then fashion. So let's pass it in. And we are copying it from your, not from the list that we created while giving the admin the option of, you know, selecting from a dropdown menu. And that's because we are already matched. Then the name of the category products over here, it's going to be called essential earnings. Then we need appliance earnings. And let me just name this correctly. Alright. After that, we have book earning books, earnings, and fashion earnings. Great. Now we just need to send it over. So let's create an object for that called earnings and then it'll include the total earnings and all these category earnings. So we can use the shorthand syntax and pass it in essential earnings, appliance, earnings, books, earnings, and fashion earnings. Now we can just use res Jason and send this earnings that we created. Great. So we have this admin analytics. Now we just need to display those analytics. So what we can do is go to the client side and close admin. So we have a new screen now called analytics, underscore screen.dot import the material dot and create a stateful widget called a analytics Screen, call it as a constant. And now we are going to return a column. This column is going to show the graph and the total earnings, but before showing that let's, you know, create an API for that in admin services. So we'll quickly go to the admin services and here we need to create a get request. So let's see if we have a get request already created and we already have that. We need to make some changes earlier, but that's fine. So here have now here, instead of returning a list of orders, what we are going to return is a map of string com dynamic. And that's because you're not converting anything, right. We will get that data in a map or string, and then we will create it in a new refined map or a string, and then get and display those earnings. So we have the earnings, we will require better context. And now this will be of sales. And for that, we are going to create a new model. This sales variable is going to help us plot on the graph. So for that, we can create a new model so we can create it in the admin itself, because this is not going to be a public model. It's going to be only for the admin to see. So we can create a sales model there. And it's going to be very different from what we've already created, because you're not going to have Jason serialization or copy with function, anything like that. So here we are gonna have class sales and it'll just have a string of label of what to display and then the total earning. So we have final end earning and take the sales, pass it in this dot label, this dot label, then this dot earning. And this is not even a name construction. And this is what we are going to have list of order list of sales of sales. After that, we're going also going to store the total earning. So now we're going to return these both as a map sales and the total earning. So you are, uh, let let's quickly pass in the admin. So we will have, well, let's see admin slash analytics passing the required header. It's a get request on nothing else is required. Also the total earning can be zero for now and in on success, things are gonna be very different. So let's remove it. So what we are going to have is first of all, convert the response in adjacent in a normal format. So we are going to decode that Jason, and we need to call this, let's say response so that it's different from this response over year, after that, we need to set the total earning a total earning will be equal to rest points. Don't use risk because the response is adjacent format. You can't access it, but this response is dynamic and it'll just decode that adjacent data. And we can access total earning on it, make sure that this total earning away is similar to the admin route that we passed away, which is total earnings. And we've already made a mistake. So let's fix that after that, we need to add to the sales variable, theLabels and all the sales model. So we have sales and we need to pass in the labels. So the label's very first label is going to be mobiles. And these labels are basically, what's going to show up on the graph. So that's what we are creating because we directly need to show it on the graph. So we have mobiles and then we have response of mobile earnings <affirmative> and then we need to add more, but let's quickly verify that we are going correct. So we have mobile earnings and all of them have an S at the last, so there's no scope of error now. So let's quickly add these four new categories. So we have essentials passing, essential earnings, then we need books. So we have book earnings. And now I'm again, confused if I named it correctly, Nope. We need to access books earnings. Then we have appliances. We will access that using appliance earnings and then finally fashion, which will be response at fashion earnings. After having both of these created, we need to return a map, which will be first of all, the sales. So we'll pass in the sales and then the total earnings, which will be total earning, Or you can just rename this. But I think just to have so many variable aim is going to be disturbing. So let's pass in total earnings itself. Now we can go to the analytics screen, create an in edge state function and remove the to-do part and also create, get for, get earnings, take this, get earnings. And we are going to call this asynchronous and now we will finish the data. So again, final admin services. Admin services is equal to admin services, create a global variable of total earnings. So we have end total sales, which can be nullable because the total sales can be zero. But if we pass in Nu it can be nullable. So we can check that way and similar thing for list of sales. So we have earnings. Now, what we will do is to it in a variable called where variable earning data, which is equal to elevate admin services dot get earnings pass in the context. Now, this earning data is a map. If you, however, this map string dynamic, because the return type of this function was map string dynamic. Now we need to set this to total earnings or total sales, which will be earning data At total earnings. And then earnings will be equal to earning data at sales. Then we need to set state and yeah, we have it done. Now. Uh, now the thing now, why we created this in a separate variable so that we don't have the call, the function, this function two times, right? Otherwise what we would've to do is pass it in over here, like this, then like this, remove this and remove this. And that would be really bad, you know, calling the function two times. So instead, what we are going to do is earning data and then save it like this. After that, we are going to check if earnings is equal, equal to Nu, then we need to show a loader and <affirmative>, and this now earnings is not our, the sales is not the total sales, sorry. So if either of them are Nu, we want to show a loader, otherwise a column. Now this column will be children. And the first child that we need is a text showing the total sales so that we finally have an output on the screen. So we have total sales pass in the dollar awaySo that we get total sales, variable, and pass in the dollar sign. After that, we are going to have a style and we are going to call this as a constant textile of font, size 20 and font, weight of font weight. So now if we see the output, we can see anything because we need to bind this analytics screen. So let's quickly go to the admin screen and pass in the constant analytics screen. After that let's restart and see what we are getting.So yeah, if I go there, we can see total earnings as 2008. And we placed an order of 2008, which is great. It's working now after this, we need to show a chart. And for chart, we are going to use a plugin known as charts, underscore flutter. You can even search FL underscore chart, which is a good library. This is a very powerful library. You can see that. And, uh, you can see the graphs are even more, better and very customizable. But for this, we are going to use charts under score flutter. So let's quickly add that dependency, stop our app execution. And in this admin create a widget known as category products chart. So that will allow us to have our own chart displaying. And in case we want the graph to be seen on other places. This can be a very reusable thing. So your first of all, let's import material dart, and also let's quickly run without debugging. So we also need import of charts underscore fluter fluter dot, dot as charts. All right, now we can create a stateless widget so we can call this, let's say category products, chart.And now we are going to return. What's known as a bar chart given by this very plugin charts flatter. This requires one argument, one positional argument. So we can pass in series list. And what is the series list? We are going to accept that from the constructor. So we have final list of series, which is another thing provided by this plugin. And it's going to consist of sales and string. And we are going to call this CD list. We are going to require this through the constructor. Also import sales away up after having series list. That's all we can do, or we can set animate set to true. So whenever we come on this screen, it'll make sure that this graph animates in a vertical direction or whatever animation has been given to it. So here we can go to the analytics screen and put the trail in comma also, <inaudible> now we can use category, product screen, or products chart and pass in the series list. Well, it's going to be CD, right? So we have series and then we need to pass in the ID. Well, the ID is going to be sales. It's not going to be outputted on the screen. Then we need to pass in data. And we have the data already, which is earnings. You can see, it requires a list of sales and we've already passed in the earnings. After that we need the domain function. And this domain function is what's going to show up on the X axis. So here we are going to pass in sales dot label. And now we need to create an instance variable of sales, but actually we don't need to create that domain function will already give that. So here we are going to receive sales of sales and other thing that is not useful for us. And then we can ask sales dot labor and measure function is going to be the why access. So now we have access to earning and there we have it. Now you can see, we are getting this error. And this error is mainly because, because the category products chart is going to have, well, this chart's flatter, and this is also flatter. So what we need to do is as charts use this, and then our error goes away over year, but near we have to use it like charts dot category products, chart, not this actually charts dot series like this, because this is our custom widget, but the CD is provided by the plugin. Great. Now, if I come over, we should not be able to see anything. Yeah, we get that end of flow error. And now we need to specify a specific height for this. So we can grab this with a size box and specify the height. Let's say two 50 and let's see what we get. You can see we are getting it correctly. So let's quickly go where, and we have that shown as well. That means our graph is working and it's showing us that correctly. So now having all of this created, we can come back to the user side and create the last function that is logging out. And then we can test it on Android to see if there's any bug or anything, then we can deploy our own server. And then I think we are good to go. All right. So we are back in the user side of the application. And now if I click over on the account screen, you can see we have the log out button ready. We just need to click on this and log out. So let's quickly go there. Let's close all the say files and go to our very last feature, which is the top buttons year. We have the logout and it's in account. So we need to go to their services and add the logout functionality. Well, we will avoid logout and we will require a build context, and then we need to create it asynchronous. Then we can have a try and a catch block in the tri block in the catch block. We'll have a show snack bar, obviously, where we will show E two strength. All right. Now, what do we need to do well to log out. We need to understand how logged in works. So whenever we try to log user in, we are going to, we store their user authentication token and share preferences. And then based on that token, we are checking if that token is there, That means that the user is logged in. Otherwise the user is not logged in. You're not storing the user's logged in condition anywhere in our database. We are storing that on the user's device itself. So we need to get access to shared preferences, shared preferences, which will be equal to shared preferences dot get instance. Now, after having instance to that, we just need to make sure that we set the string empty so that whenever we come to this odd service where we get the user's data, which is when the user, just when the application starts, we are running this functional function. So whenever we get this user string and the token can be now, so the token here is empty. So it'll tell us that the token is not valid and then it'll not get us to the home screen. So yeah, we just need to do a eight shared preferences. Set string key will be Xu token, similar to what we had in the art service, which is this Xu token or token. And we need to make sure that it's lowercase. So let's quickly type lowercase and the value it's going to be an empty spring. Great having that. We are making sure that there is no more set string or anything. Now we just need to make sure that we push the user on the O screen route name right here. We just do navigator dot, push named and remove until O screen.name. So let's quickly have that. And then we can set out set to false. Great. So we are going to go to this odd screen and it'll pop off all the other screens that come in between. Also we can set provider to Nu but, or empty strengths, whatever, but I don't think there is any use case for that because anyways, we are on back on the main screen, it wouldn't really matter. So if I click on log out, no nothing would happen because I have to bind this function. So let's quickly go by and use account services and you need to create that instance. So let's copy this and our final account services. And now, instead of, you know, creating this account services instance as final and thus, because of that, we need to create this as a stateful widget. We're going to remove all of this and convert this to a stateless widget. And now we need to create a constructive for that. So we can add key to constructors and yep. We have it. Now we can just use account services so that you know, like this, because if we create the instance of the account services over year, it'll become a stateful widget. So here we have account services dot log out, pass in the build context. And yeah, we have it. Now, if I click on log out, we went back to the odd screen. And if I tried to go back, I'm not able to go back. I'll restart the application and we are still not able to go there. So that means our app is working and it's completed. We have completed so many features. I hope you learn something from it. Now, the last thing that we need to cover is deployment. And then after deploying it, we'll test it on the Android device as well. So here we to deploy it, we are going to use heroku.com. It's a cloud application platform. You can see it over. It allows us to host our servers over, which will provide us with URL, which we can replace with our, which is the IP address because IP address will make sure that it only works locally. When we are connected to that particular wifi of which IP address we got. And with Heroku, we are able to get a server where we can deploy our server and it'll be accessible to everyone and we can publish it out. So let's quickly sign it up, sign up. You need to enter all of this, the first name. So I'm gonna pass in, run our, and then the email address. So here we need to pass in your email address and the primary development language I selected as no J you can just use any other thing you want. It really doesn't matter for now. So now let's click on create free account. All right. So I've logged in and here I am terms of service. I'm not in Italy. I'll just click on accept. If you are then select that option. So here VR welcome to Heroku account has been set up. Let's get started. So now we need to create a new app. So let's quickly create a new app. We need to enter the app name. So we are going to name this Amazon clone, and this should start with the lower case. So we have Amazon clone. Yep. This is not available. So we can call this Ivan and <affirmative> and Amazon clone R is available. So we have United States based on this name, you're going to get a URL. So make sure whatever you type in is according to the URL you wanted, and I'm going to choose a region United States itself, and you can choose Europe, whatever you want. It, it wouldn't matter after that, we need to deploy to deploy it. Either you can use the Heroku CLI or you can connect with, get up now to connect. I'm gonna connect with, get up. So for that, what I'm going to do is stop this server execution, clear off everything, and now run, get in it, get, add, get commit M uploading server. And then also, actually before doing that, I would've preferred doing node under core modules, ignoring them. So if you're familiar with kit, what you need to do is dot get, ignore, and ignore the node module. I've not done that, but make sure to do it after that, we need to set up and create a, get up accounts. I'm quickly going to create my, get up account, your click on new and create Amazon server tutorial. I'm just going to repo, delete this repository after trying it out, you know, but now we are going to click on create repository three when we need to make this public. So yep. Now we need to add, get remote, add origin, sorry, not origin. Get remote ad pass in this URL. And I think we need to pass in origin and then we need to finally do get push U origin master after this. It'll make sure that it uploads to get up so we can clear it off. And if you're not familiar with get up and mention the resource in the description below from where you can learn it out. So we have our Amazon server tutorial pass in so I can come over connect to get up. I'm going to authorize Heroku for now pass in my password. So after getting the URL from there, you need to update your global variables. You are writing and update your, remove your IP address. And instead of that, put that, and also before uploading, what you needed to do was I forgot to tell you over here in this port, you need to specify something known as process dot ENV dot port or, or 3000.That means that it'll look up. So when we deploy node will give it a particular port. It'll not be 3000. It'll give it a random port. It can be 3000, but it will not be 3000 always. So here we will have process dot EMV dot port. So it'll take in that port, that node gives us otherwise, if it's not mentioned, then we can take 3000 forward. So after having done that, you have passed it over. There's no need of this anymore, so you can remove it. But even if you keep, keep it, there's no worry about it. And then finally, again, deploy it to Heroku, get the URL, and it'll be the same URL after deploying it, redeploying it. And then you can go to the global variables, change our, and then our app should work perfectly. So now I'm going to run it on pixel five ator and see if it's working or not. So I'm going to run without debugging and check if there is any error in that debug console, and here you can see, we are already getting an error. And if you got this error and I'm looking into it late, you can just go to the bill grade L file. And here the minimum SDK version is 19. So make sure to add that and now run it without debugging. All right. So our app is built and here we get the create account and sign in thing. So let's quickly create an account. I'm gonna call this R R pass in the email, let's say R email.com and pass in R way three. Let's say so I'm just going to click on, sign up account has been created, then click on, sign in and then sign in. And you, yeah, but we are able to see the deal of the day. We have the whole different card, and now let's actually sort some product, which is MacBook. I'll click on enter, and I'll add to card, rate it with a 1.5 star and then go to the card, proceed to buy an item. And here we have the Google pay button. You can see if we click away, Google pay requires a Google account to be set up on this device. We need to set up Google pay. You can try it on a real device. So yeah, I'm gonna have, uh, so here we are gonna have 1 0 1 fake street, and it doesn't really matter if we enter or not, because we can't place an order, but rest of the things are working. It feels like that. No orders are there still. Then we can click on deal of the day. We can search products after that, we can click on log out and we are logged out again.So this is a bonus section in this tutorial because flatter three has come up. It was announced on Google I, so yeah, we are. So what we are going to do is see if there is any breaking changes, I've upgraded to flatter three. If you want to upgrade two, you can run flatter upgrade, and then it'll show you all the necessary stuff. If everything goes well, it'll show you like this. Otherwise it'll also show you the suggestion of how you can install it properly, or you can search it on the net. So I have it here. What I'm going to do now is open vs code and see if there is any upgraded version or there's any B changing break breaking code. So I'm just going to exit via code update and open it again and open it again. So yeah, we have it. Let's see if you're getting any suggestion here.You can see the flatter version is Florida 3.0 0.0 and the dot version is now 2.17. Great. So now what I'm going to do is try and run the application to see if it's working or not. So let me get my I simulator and also keep track of all the warnings that show up and everything that shows up. All right. So our app has launched, but we get these warnings and I've been looking about this warnings throughout my discard server and all of the servers I'm in. So this has nothing to do with it. It's just that flatter when it upgrades again to some other version, they'll fix all of these things. But as of now, we don't need to worry about this. This is inside flutter code itself. So we can just ignore these for now. Let's see if you're getting any warnings or errors anywhere. And it doesn't seem like we do. Let's remove all of the warnings and continue in our application. So let me quickly remove all of these things that have not done. And yeah, now we don't have any warnings, so let's close all the save files, then save all the other file. And then again, close all the safe files. Great. So now if I come back over here and pass in the sign in, so let's say test 1, 2, 3, gmail.com and pass in the password as test 1, 2, 3, click on sign in, and we are signing in here. We are, everything looks great. And there doesn't seem any other error. Now, in case you don't know about flood three, it introduced usage of material three in our application. So you can go in the main door dot file. And in the team data use material three. Yeah, we have it, the option and the property and set it to true after this, you know, it wouldn't do anything great in our application, except this part. You can see, this looks much better.Even this, you know, it's rounded and it's making it on its own. You can see the ripple effect away. This has also changed because of material three. And now this doesn't really look like Amazon, but it looks cool though. So I'm not complaining there. The proceed to buy items. You can see it's rounded on its own. If we increase this, it doesn't matter. And here we have it. The icons also seem to be a bit changed and nothing else will really change in our application because we are using designs from scratch, but you can see, it looks great even the effect of a year. So if you want, you can use this. Otherwise just use the normal thing that we've created and we are back to normal, but I like this better. So I'm going to use material three and just add a comment that you can remove. This line can remove this line for anyone who's referring to the source code. We can have this, and this will keep coming until the next version of flood, but I just wanted to know, show it to you that nothing is changing your in our code so you can follow along and that's it. So this was the tutorial. Thank you so much for watching. See you in the next video.\n"