Flutter & Dart Developer Course | Flutter Complete Tutorial For Beginner to Advanced level

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in today's video I'm going to be giving you guys a complete crash course in flutter development I'm going to be holding your hand and taking you through all of the concepts you need to know to go from a complete beginner and flut development to somebody who is confident using this framework we're going to be developing a recipe application which is going to work on both IOS and Android and the actual things that I teach you can also be replicated if you want to build apps for the web or desktop using flutter so let's firstly take a look at the actual application that we're going to be building and then I'll also talk about the concepts that you're going to be learning throughout this video so first things first our recipe application is going to present us with a login page our application is going to support logging in using an actual API sending a network request with our credentials and then getting a JWT token back if for some reason our login isn't successful for example we do not provide the correct username then our actual login operation is going to fail and it's going to give us a prompt letting us know that hey the operation failed but if if the actual credentials are correct and we log in it's going to take us from this page to our actual recipe book page where we can see a list of all of the recipes that we can actually create or cook I should say at the top we're going to have a filter which is going to allow us to filter these recipes by the actual meal type and all of this information is then again going to be retrieved from an actual API and these filters are also going to work with the network requests in Tandem and when we updates the filters then the actual information that is displayed will also be updated so let's just say that I want to view lunch options if I click on lunch it's going to send another retro request and only ask for meal types that are lunches once we are comfortable with an actual recipe that we've decided we want to cook we can click on it and it's going to navigate us to the actual recipes detail page where we'll be able to actually see an image of the actual recipe and some more information with regards to what the ingredients for this recipe are how to actually make this recipe the review what the prep time is the cook time it the title as well as what the actual region for this dish is as well as how complicated it is to actually create so throughout building this application you're going to be learning everything you need to know about flutter we'll talk about how to initialize a flutter project then from there we'll move onwards to talking about what the fundamental concepts of flutter are how flutter works we'll talk about widget State Management Network requests how to work with forms what different widgets are available to you and how you can use them to display information in different ways within your application we're also going to be talking about navigation and everything else that you need to know such as for example coding your product using good coding standard so that easily maintainable the actual use of external packages within this actual tutorial is going to be kept to the bare minimum and we're going to be using everything that comes with flutter out of the box to achieve most of this functionality because I want to show you guys all of the things that you can achieve with just flutter there are situations where you might want to replace certain elements of flutter with something else that can maybe be better address these issues such as for example State Management or navigation but for now we're not going to be delving into it so this is going to be something that even beginners can start with and it's going to be an excellent tutorial that you guys are going to enjoy a lot so to get started the first thing that I'm going to let you guys know is that the only prerequisite for this tutorial is that you have flutter installed on your system and set up correctly if you are confused as to how to do this I already have tutorials for this on my channel for both Mac OS and windows so you can take look at them links to them will be on the screen as well as down in the description below so take a look at them and then you'll be up to speed but once you have flirt set up then you and I are at the same starting position so let's get going so the first thing that we want to do is actually create an empty flutter project or initialize the project I should say that then we can code in so to do that what you're going to be doing is actually opening up terminal or if you're using Windows you can open up Parell and then basically you're going to be navigating to an actual folder where you want to place your flutter code in my case what I want to do is actually place this code within a folder on my desktop so what I'm going to be doing is doing CD which stands for change directory it should work on both Mac OS and windows I'm going to go to desktop and then from there I'm going to go into a folder called development and press enter now I'm within this development folder so here what I'm going to be doing is actually using the flutter create command but before I do that I'd like to quickly mention that if you guys are confused at any point I've left a link to the source code for the complete project down in the description of this video so feel free to take a look at it if you're confused at any point so before we actually use flutter create let's actually talk about the other useful commands that might come in handy when you're actually following along with this tutorial so one thing I recommend is that you make sure that your flutter version is as close to M as possible by doing flutter space- Dash and then version and as you can see I'm on flutter version 3.9.0 so any 3.19 version doesn't matter it's zero or a minor version of 3.9 should work so if you are facing a lot of errors or things like that when you're following along then I recommend that maybe you downgrade or upgrade to the flutter version that I have once this is done the next thing that we're going to be doing is also talking about the flutter doctor command which you can do by doing flutter and then d o t and what this command basically does is that it analyzes your flutter installation and lets you know if there are any problems before you actually proceed with this tutorial or actually any flutter development so as you can see I can see that practically there are no issues with my actual flutter installation besides the fact that it's telling me that I'm browsing on the local area network but that's nothing that we have to worry about as you can see I have text for everything so we can continue so now that we've basically taken this out of the way let's initialize and create our flutter project so to create my flutter project what I'm going to be doing is doing flutter create and then I'm going to be giving my project a name in this case I'm going to do recipes uncore app and then I'm going to press enter and as soon as I press enter what's going to happen is that this command is going to run and it's going to initialize an empty flutter project for me once this is done what you can do is actually just close down terminal or partial whatever you're using we don't need it anymore and you can open up visual studio code and once you've opened up visual studio code all you can do is navigate into the folder where you created the flutter project and then drag and drop in your actual project within Visual Studio code like so and once you've done what you're going to see is that you're going to be presented with a codebase that's going to be similar to what you're seeing here here the only thing that you should be concerned with for now is the lip folder and this is the folder where all of our source code for our application is going to go for now if you went into this folder you're going to see that we only have the main. file and this is the starting point of our application and specifically within our main. file we have a function called Main and the main function is the basic entry point for our application when we actually start running it and from Main we call a function called run apppp if you hover over it as you can see it tells that it inflates the given widget and attaches it to the screen so run apppp basically runs our actual application and then attaches it to the screen and then here we pass in the actual application that we want to run so this is the basic flow of how our flutter application actually starts up so before we proceed with anything else let's quickly talk about how flutter works now there are many Frameworks that are out there for mobile development the most famous One besides flutter is react native so if you come from the react native world you might already know how react native works but flutter Works in a totally different way flutter basically works like a game engine all of the pixels on the screen are actually generated by the flutter framework and we do not rely upon any underlying components of the actual native system that we are running our application on to actually produce graphics on the screen so all of this is handled by flutter so flutter looks totally different than react native in react native you might have heard that you define some kind of an element and then that element gets mapped to the native system element on which your application is running that's not how flutter Works flutter works like a game engine where the whole framework is responsible for every pixel on the screen and the framework itself determines what to draw on the screen and then display to the user so to help us in developing apps what the flutter team has done is actually given us some packages that we can import within our actual project that can allow us to show to the user certain UI elements that are designed to certain standards namely being the material UI system and the copertino UI system so the material design system is the system of design that is incorporated by Google and that's the design language that Google uses within their products and then on the other hand we have copertino which is also a package that you can import and this is a design language that Apple uses within the products that they build so if you want your application to have a feel and wipe similar to how Android apps look then you might want to go with material if you want to have your application have a look or feel similar to Native iOS apps then you might want to go for a copertino package in this tutorial we're going to be talking about the material package so basically our UI elements that we are going to be working with are going to basically mimic the design of the actual material design that is created by Google so now the next step in our discussion is going to be talking about widgets which are the most important Concepts when it comes to flutter development in my opinion a widget is a key component of the user interface in flutter widgets are used to describe the structure and layout of your application's UI elements such as buttons text field images containers and we'll take a look into these and the UI is rebuilt when the widget tree changes because flutter is built on a reactive architecture so what is a widget tree well flutter apps as I had alluded to before are constructed using a hierarchy of widgets and this hierarchy of widgets this composition of widgets is known as a widget tree at the very top of our widget tree we have a material app if you're using the material package as you can see here or we might have a copertino app if you were using the Cupertino package we're using the material app here so this is at the very top of our actual widget tree and then we have widgets nested within this and then this tree of widgets actually constructs the UI of our application and this is how basically widgets work in a nutshell there are much more details that I can get into but for now this understanding should be sufficient enough for you so now with this done let's do this let's actually take everything that's in our main. doell besides the actual main function and let's actually remove it so to do that what I'm going to be doing is basically removing everything in this file and then now we're just left with a main function which is calling run app which expects us to pass it a widget that then is going to get displayed on the screen so the first thing that I'm going to be doing is that I'm going to be creating a widget and this widget is going to be called my app so how do we create widgets well there are two types of widget within flutter one is a state full widget and one is a state L widget stateless widget basically refers to widgets that do not change their state do not change the data that's within them while stateful widget refers to widgets that the data within them changes during the life cycle of your application for now what we're going to be doing and usually what happens is that the very top level widget within your actual widget tree is usually a stateless widget and widgets within them can be stateful widgets so the data within them can change but at the very top level we don't need a stateful widget wiet so let's create a class let's call it my app and let's say that this extends a stateless widget once this is done you're going to see that it gives me an error saying that we are missing a concrete implementation of the status widget. build function so let's do that so to do that you can quickly hover over this click on Quick Fix and then say create one missing override and this is basically going to create the build function and this build function needs to be defined because we are extending our stateless widget Class A build function on an actual widget defines how that widget is built and this is exactly what now we're going to be doing so what I want to do is that within my build function instead of throwing an unimplemented error I want to return a widget and what is the root widget within our widget tree going to be well it's going to be a material app I'll press enter and that's pretty much it and if I hover over this you're going to see that it basically tells me all of the different actual parameters that this material app takes within its Constructor and at the very bottom it tells us that this creates a material app so the material app is basically going to lay the foundation of her widget tree it's going to lay the foundation of our application and then now we're going to be nesting widgets within this to actually create our application so let's get going with what our material app is going to look like the first thing that I'm going to be doing is giving it a title and the title in this case is going to be our recipe book app so I called it receip book like so once this is done I'm also going to be giving some team information to my material app so this tee information is basically going to let the material app know what the color scheme and the other visual composition styling for my application is going to be like so this if I hover over this you can see is going to expect an instance of a object pass to it which is of type theme data so let's instantiate a theme data object and as the name suggests this basically defines the theming for our application within this I'm going to say that we're going to define the color scheme of our application and that is going to be color scheme color scheme. from seed and then I'm going to give it a seed color which in my case is going to be colors. de orange so this is basically going to generate the color scheme for my application from a seed color that I pass which is colors. deep orange then besides this I'm going to set the use material 3 property to be true so this means that we're going to be using material components that are basically going to reference or adhere to the standards of material 3 and then I'm going to set the app bar theme and for now let's just set the app bar theme and then we'll actually discuss what the app bar is so I'll say that here I'm going to Define abar theme like so and I'm going to say that within my abar I want to change the text styling for the title and then this is going to be text style like so and here I'm going to do color is colors. black the phone size is 25 then the font weight is font weight. bold like so and that's pretty much all we had to do and then I'll do command save now you can see that it's giving me an error thing that I can add con with the Constructor tool improve performance so let's add the con keyword and let's do command save and there we go so now if I try to run my application there is going to be an issue and that is that for now our material app is not going to know what it should display on the screen so for that we basically need to set the home property for our material app so on my material app after I've defined the theme I'm going to define the home property and this home property for now is going to be nothing because we haven't created an actual widget that we'd like to display when our actual material app is then rendered on screen so let's actually create a widget well for this what I'll do is that to keep my code maintainable and organize my code I'm going to go under the lip folder I'm going to create a new folder here called Pages underneath of which I'm going to create a new file and I'm going to call this login page. Dart then within this I'm going to say that I'm going to create a class it's going to be called login page and it's going to extend and you need to now guess is it going to be a stateless widget or a stateful widget well this time we're going to be using a stateful widget and the reason for that is because we are going to be managing some data some state within this actual widget and that's going to change during the life cycle of our actual widget so that's why we need to implement a stateful widget so for that I'll say stateful widget and then then I'll open up the actual class definition and this stateful widget comes from the material package as well then an actual stateful widget requires us to actually Implement a concrete implementation of the function create State similar to how we did for build so let's create this implementation and what create State basically does is that it defines how the state for this widget is created so to make this work what I need to do is create another class and this is going to be called underscore login page state so this class basically manages the state of our login page widget and we are using an underscore before the name of our actual class to mark it as a private class so it's not accessible outside of scope of this file and I'm going to say that this extends a state of type login page and this is the basic workflow when it comes to working with stateful Widget a stateful widget always has a class that extends the state stateful widget and then a corresponding State class that basically manages the state for the widget so in this case the login page is the actual widget that extends the state full widget and then to manage the state of our login page we use theore login page State class and then basically within the actual login page State class I need to create the build function here we're basically going to be defining how our widget looks so for now what I'll do is that within here I'm going to say that I'm going to return a scaffold so it's an empty canvas for us to draw stuff on that's what a scaffold is and we use scaffolds usually when we want to define a new page within our application so now that this is done within the create State function what I'm going to be doing is I'm going to be removing the throw unimplemented error instead of this I'll say that I'm going to return a instance of our login page State like so and do command save and now all of the errors on my login page class should be fixed so let's go back to main. do and let's set the home property for the material app to be our actual login page like so press enter do command save and as you can see at the top it Imports the login page class so now that this is done you can see that it's letting me know that the Constructor that's being called is not a con Constructor so let's remove it I can also see that in my test folder it's giving me an error for the widget test so for now what we can do is just delete the test folder because we're not going to be implementing any test within our project so let's just delete that and now we're ready to test our application so to test my application what I'm going to be doing is that I'm going to make sure that I have some type of a main. file open and then from there what I'm going to be doing is actually opening up an actual simulator so let's talk about how you can open up simulators I'm assuming that for your flutter development environment you've actually already set up emulators and within the actual vs code that I'm running youve also install the extension for flutter which I can show you which one it is but if you follow the tutorial that I link to at the start of this tutorial which were the ones where I showcased you guys how to set a flutter on Mac OS and windows then you should already have it but basically if you don't then you need to install the flutter extension inside of Visual Studio core and then open a main. file and then you can click on the button at the very bottom where it says Macos it might say something else for you and it's going to pop up an actual list of all of the simulators that are available through you to actually test your application or run your application on in my case I'm going to do start pixel 7 and this is going to spin up a emulator for me on which I can test my application at the bottom as you can see it's telling me that it's waiting for the pixel 7 API 34 to connect and once this actual simulator launches correctly you can see that now at the bottom the actual name of the target where we're going to be running our application on changes to pixel 7 so this means that I've selected pixel 7 to be the actual Target where I run my application then what I'm going to be doing is that I'm going to be coming to the the top saying run and then doing start debugging you can also do F5 on the keyboard and that should do the same thing so let's do start debugging and this is going to start running my application you can also use the actual button here with a bug and then a play button to actually debug your application and as you can see it's telling me that it's basically going to launch this application onto the simulator so now what we need to do is basically wait for the actual build process to complete so as you can see it lets me know that now it built the actual application and it has basically deployed that onto my actual simulator and I can work with it so to just quickly test out that the hot reload functionality and I'll come back to what hot reloaded Works what we can do is come to loginor page and within the login page I'm going to come to the login page States build function to the scaffold and here what I'm going to do is set the background color to be colors Dot and I'm going to do green if I do command save you're going to see that automatically the changes that we've applied to the core are going to be reflected on the actual simulator and this is how we know that the hot reload function is working and then besides this I'll also check the the actual restart function is working by just clicking on this and this is going to completely restart my application completely start it again and this is useful sometimes when we get exceptions or we get some kind of an error within our application where hot reload might not fix it so we might want to restart our application completely and get rid of all of the existing state and everything like that so for that we can use restart but now everything looks good so we can actually get started with designing our login page so before we actually design our login page we can actually take a look at how our login page looks so at the very top of our login page we have some kind of a text that says login then we have a title that says receive book which is the name of our app we have two text fields that basically allow us to put some information within them which pertains to the username name and the password talk about them and then finally we have a button so a whole bunch of different things that we need to implement on this login page so let's talk how we can do this so to get started the first thing that I'm going to be doing is actually implementing the title at the top so how do we do that well to do this what I'm going to be doing is I'm going to come to my login page States build function to my scaffold and on my scaffold I'm basically going to define the ab bar property so this is the ab bar which if I create an instance of this you're going to see is going to display at the very top and for now it's not showing us anything but this app bar basically refers to the top bar that you see in many applications that basically shows sometimes the information regarding the actual page that you're on and maybe a button to open the drawer or thing like that so in our case what our actual AB bar refers to is this top part of our actual UI Where We Are showcasing the title of our application on the actual homepage as you can see on the recipe detail page as you can see the app bar gives us a button to go back and then also on the login page where it shows us the login title so to add a title to my app bar widget what I'm going to be doing is defining the title property and as you can see it expects a widget to display text on the actual screen for our flutter application we use a widget called text and then we pass it a string which defines the actual text that we want to show in our case it's going to be login and there we have it it's showcasing the actual login text within our AB bar at the top now if I want to Center this what I can do is that I can actually add a property to my app bar called Center title and set that to true and this will put login in the middle and this is practically all we had to do and the reason for that is because the styling for this text comes from the actual tee data that we had defined where we have defined the ab bar theme and specifically the actual Tex style that needs to be applied to the title that is for this actual AB bar so you can kind of see how things are kind of linking together now and hopefully it's making sense to you but if you're still confused just keep going and things will slowly start making sense to you so now the next thing that I want to talk about is all of the other stuff that we see on our login page which is basically the title The text fields and then the buttons how do we add these well on our scaffold we have another property which is called body and body basically expects us to pass it a widget which basically defines how the body for the scaffold looks how the body of the page looks what I want to do in the spirit of actually keeping my code organized is actually create a function called build UI and then basically set the return from that function to be the body then within my login page State class I'm going to say that I'm going to create a function which will return a widget it's going to be called the build UI and then what I'm going to be doing is opening up the function definition and for now I'm going to say that we are going to return something and what are we going to be returning well if I take a look at my UI closely I can see that I have UI elements that are basically stacked in a vertical manner there's a title below which I have text Fields below which I have a button so to this kind of functionality within flutter we have a widget that's called a colum widget which basically allows us to embed widgets within this and then organize them in a vertical manner so this is why we use a column so I'm going to add a column widget and then the column widget expects a list of children which basically are the actual widgets that are going to reside within this column so for now the first thing that I want is the title so let's create that so then again what I'm going to be doing is that I'm going to be creating another function I'm going to say that this function will return a widget it's going to be called underscore title I'm going to open the function definition up and by now you guys might know that when we want to display text we use the text widget and then we pass a string to it which basically defines the actual text we want to display on screen so in this case it's going to be receive book like so and then I'm going to take this title I'm going to come back to my column to the children's list I'm going to add the title here and then add the parenthesis to invoke the function and do command save and now if I come back to my application you can see that we are seeing a very teeny tiny text that says receip book so let's fix the styling for this so I want to make this text a bit bigger and other things like that so for that on my text I have a style property that basically defines how our text is style this needs to be of type text style so I'm going to initialize a new instance of textile and here I'm going to pass the phone size and the phone size here is going to be 35 and as soon as I do this and do command save using the power of hot reload it's automatically going to reflect this change and now the size is much bigger I also want to make the font less thick so I'm going to define the font we property and I'm going to set that to font weight and then I'm going to do w300 and do command save and since this widget is not going to change I'm going to add the const keyword before it just to improve performance so now that this is done the next thing that I want to do is actually Center this actual title so to achieve this what I'm going to be doing is coming to my column and here I'm going to Define firstly the main axis size for my column so since a column aligns its children in a vertical manner then the main axis of the column is the vertical axis and we're also going to be talking about something called the cross axis and the cross axis in this case for a column is going to be the horizontal a axis so on the main axis I want my column to take as much space as it can and then I'm going to define the main axis alignment so the main axis alignment basically refers to how are the children basically aligned within the column in the main Axis or on the main axis I should say and in this case that's the vertical axis because we're using a column so there are different alignment options we can use for now what I'm going to do is set the alignment option to be space evenly and then we'll talk about the other ones later on or let's actually set this to start so I want stuff to be aligned from the start of our actual column and then finally I'm going to define the cross axis alignment so how are elements aligned to each other on the horizontal axis so I want the elements to be in the center of the actual column so for that I'll do cross access alignment do Center and do command save and that's pretty much all we had to do nothing's going to change for for now but just keep on going with me and you'll soon see what's going to happen so now that this is done let's actually move on to the next step which is to actually showcase these text Fields so how do we do that well to do this what we're going to be doing is actually creating a new function and I'm going to call this function undor login form open it up and then within this I'm going to say that we are going to be returning a widget called a s box and I'll let you guys know what a Siz box is later on but for now let's come back to our actual column and then I'm going to say that after my title I'm going to show the login form and do command save a size box is basically a widget that we use that can have a child within it and it's basically used to restrict the size of the child that it contains to specific dimensions that we tell it in my case what I want to do is that I want to say that whatever child that's going to be within the size box it's with is going to be the following and since I want my actual application to be responsive I'm going to be basically taking into account the actual width of our device so to access the width of our device there are multiple ways you can do this in flutter but one easy way to do this is by using media cury so I'm going to do media query. sizeof context. width and then I'm going to multiply this with 0.90 like so and do command save then I'm going to define the height for my sized box and I'm going to do the same thing where media Cur do size of context and then I'm going to do do height and I want this to be 30% the height of the screen so this size box is going to have the width which is going to be equal to 90% of the width of our screen and the height is going to be 30% the height of our actual screen then the child for this is going to be for now a text form field like so and I'll do command save and you're going to see that now an actual text field is going to appear appear on our actual screen which we can interact with and put data into for now nothing's happening with this actual text field we're not managing anything within this and this is basically a widget that we can use to actually take input from the user so now that we have this text form field what I'm going to be doing is removing it and the reason we're removing this is because if I come back to the actual design for my application you can see that I have two distinct text fields and these text fields basically are used to capture the username and the password from the user and they have some additional functionality that's attached to them such as validating that the user inputs a username and password and some other things like that so what I want to do before I actually add a text form field to my actual widget tree is to actually add a form widget to my actual widget tree so to my size box I'm going to add a form widget and a form widget is basically going to allow us to perform different operations on our text form field manage the state of our text form fields and a bunch of other things and make it easy for us to actually extract information from our text form Fields when we want so that's why we're using a form widget form widgets are usually used in tandem with text form field widgets to implement the functionality of actually Gathering data from the user within a form so now that I have this form widget defined for the child of this I'm going to be using a column and the reason for that is because within my form I'm going to have two children I'm going to have a text form field for the username and then a text form field for the actual password so for this what I'm going to be doing is actually using a column so the form is going to have a column the column will have some children and that for now is going to be an empty list and I'll do command save then within this columns children I'm going I'm going to add a text form field like so and then I'll do command save and there we have it now we're displaying this text form field so now that this is done what I want to do is that I want to Center this text form field within our column so I'm going to quickly do that and the way I'm going to be doing this is by firstly defining the main AIS size for my column to be main AIS size. Max the main axis alignment we can do main AIS alignment. space evenly so I want the elements within this column to be spaced evenly and then the cross axxis alignment you might have guessed it is going to be cross Axis alignment. Center because I want to horizontally Center all of the children within this column and to do that we have to set the cross AIS alignment which refers to the horizontal axis to be cross Axis alignment. Center to command save it's still not going to work just bear with me and it's going to happen once we add another text form field but for now let's just keep chugging along so now what I want to do is that I want to basically add a hint text here which basically tells the user what the actual input here needs to be so for that what I'm going to do is come to my text form field widget and here I'm going to define the decoration property and that is going to be of type input decoration so as the name suggest the decoration property basically defines the styling for a text form field and here I'm going to set the hint text to be username like so and do command save and there we go we now have a hint text that's appearing on our actual text form field and as soon as we click on our text form field the keyboard appears and when we enter our information then that information is displayed and the actual hint text disappears but once we don't have any information the hint text reappears so this is what a hint text is and I'll do command save now that this is done the next thing that I'm going to be doing is that I'm going to be basically taking this text form field copying it and pasting it again within the same column and this text field is going to be responsible for the password and then I'm going to do command save so now that this is done what I want to do is actually add some spacing between the actual title and then this form that we're seeing so how do I do that well to do this I'll come to the very top where I've defined my build UI function and the main column that consists of the title and the login form and here I'm going to set the main axis alignment instead of being do start to be let's just say for now space evenly and this way what I'm telling the actual column is that hey I want the children that are within you to be spaced evenly within the column on the main axis which is the vertical axis so now that this is done we have a place to put our username in we have a place to put our password in the last thing that I want to do is actually implement the actual displaying of our actual login button and then we can actually move towards implementing the actual login functionality or the logic I should say once we have the UI kind of completed so to do that what I'll do is that I will create a new function now and I'll say that this function will turn a viget it's going to be called underscore login button and similar to how an underscore in front of class names tells the actual code that this class is going to be a private class a underscore before function name also tells the actual compiler that these functions are going to be private so I'm going to do a login button open the function body up and here I'm going to say that I'm going to return a sized box widget like so then I'm going to take this login button and I'm going to add this within the column where I have my text form Fields after both of the text form Fields like so and do command C then now since we understand how to define the width for our size box I'm just going to quickly and copy paste this code in where we are setting the width to be 60% the width of the screen and then I'm going to set the child to be a button the button that I'm going to be using is going to be specifically called an elevated button and then before we can do anything we need to Define two parameters on the elevated button one is what happens when we click on this button so this is a call back function for now I'll just Define this to be an empty function so you can Define two parentheses first and then curly brackets and this is called an anonymous function and then the child here is going to be basically what's shown within this button so I want to show some text that such login so I'm going to do const the text widget and then I'm going to say that's going to say login and do command save and there we have it that's pretty much all we have to do so now the last thing we are going to be doing before we can actually call our UI done and then actually move towards the implementation of the logic for logging in is actually taking a look at a safe area widget and a safe area widget is an essential component within our actual flutter application that we might use we might not use depends on our use cases which allows us to ensure that the content of our app remains visible and accessible on our screen even when the device has notches status bar or other infusions so let's just say that you are going to be creating an application that's going to run on the latest iPhones which have these Dynamic Islands within them and then it's also going to run on a pixel which is going to have this camera that's going to be built within the screen I don't want my UI to be obstructed by these cameras or by these notches or by these Dynamic islands that are on all of these devices So to avoid this problem what I can do is that I can wrap my actual widget within a safeer widget and then it's automatically going to make sure that my app content remains visible and accessible on the screen even if the device has notches or anything like that so to do this what I'll do is that I'll come to my build UI function and then you can either right click on it and then basically say that I want to refactor this and then you can wrap this with a widget and a shortcut to this on the keyboard is also command shift r on Mac I do not remember specifically what's it on Windows but you can wrap this to the widget and this is basically going to wrap this build UI function within a new widget and the widget here is going to be a safe area widget and finally once I've wrapped everything within a safe area I am basically going to fix this alignment error here where all of the things are not in the center so for that what I've concluded through my debugging and as you get more experience with flutter you'll be able to debug these kind of issues is that my column is not extending to the complete width of my screen so to fix this what I'm going to be doing is coming to my column within my build UI and I'm going to be basically doing the same thing where I'm going to be wrapping this with a widget in this case I'm going to be wrapping this with a size box and then for my size box I am basically going to say that the width for this is going to be media cy. sizeof context. width so the complete width of our device to command save and there we go with that we pretty much fixed all of the styling issues so now our application looks exactly how it looks in the screenshots and what's left is to actually implement the logic for logging in so before I do that what I'm going to do is come back to the main. file and here I'm going to show you guys that if you want to basically remove this actual Banner that shows debug here from your flutter application you can basically set the property debug show checked Banner to false and this is basically going to remove the banner from here if you set this to true then it'll show the banner so that's pretty much it so now that we have the UI for our login page completed and we have a basic understanding of how to build uis in flood let's actually move our Focus towards implementing some business logic let's talk about how our authentication flow is going to work or how we're going to log in the user into our application so to get started the first thing that I'd like to bring your attention to is the actual API that we're going to be using throughout this video to actually access information from regarding recipes but also authenticate with more specifically we're going to be sending our authentication request to dummy jason.com login and this is an excellent resource I should say before we continue that's dummy jason.com because here you can get access to a lot of different apis that you can work with to improve your skills as a developer you can use these apis to build demo web applications demo mobile apps or other applications that you imagine and all of this is given to us for free so you shout out to dummy jason.com it's an excellent site that I recommend to a lot of beginner developers that want to learn how to work with rest apis so to implement the login functionality the flow is going to something like this we're going to send a request to https dumy jason.com login and we're going to more specifically send a post request and in the body of our request we're going to include the username and the password that the user gives us from these fields and then in response if authentication request is successful we should get a response back where more specifically we are just going to be focusing on the token this token is basically going to be a JWT token or Json web token which we're then going to be attaching to all subsequent requests that we sent to the server to tell the server that this request is coming from us the authenticated user that had provided in the previous step the username and password and this is just an industry practice of how JWT token works there's nothing special here that pertains to flutter this is how JWT authentication works so now that we have a good understanding of this let's go back to our code So within my code right now what I'm going to be doing is closing the main. file coming back to the loog page and let's do firstly the implementation of our form let's make sure that our form is working the way we want it to work and then we'll move on to actually extracting the information from the form and then sending it over to the server or authenticating ourselves so to work with the form as I had alluded to before when we were building the form is that when we want to work with forms within flutter we need to wrap our widgets with a form widget and if you hover over the form widget it tells you that it creates a container for form Fields so basic basically a form widget is required if you want to work with form field widgets so there are text form Fields but there are other type of form field widgets that are available to you as you can see there's form field there's text form field there's Cupertino text form field row and a whole bunch of other things such as drop- down button form Fields input date picker form Fields so different input fields that you can use to build your form and our case we are just using two text form Fields so now that we have a basic understanding of how how to create a form let's actually talk about what we need to do to make this form functional well every form requires something that is known as a key and this key basically allows us to work with the form and this key also maintains the state of the form so let's create a key for our form so to create a key for my form what I'm going to be doing is coming to the very top of my class which is the login page State class and here I'm going to be creating a variable of type Global key and specifically it's going to be form State and then I'm going to say that this variable is going to call underscore form key and then I'm going to be setting this equal to a new instance of global key like so and do command save then I'll take this login form key I will come down to where I have my form and I'm going to set the key property to be the login form feeld so now with the login form fee attached to our form I can use this to actually manipulate the form and work with it so let's actually take a look at it how we can do this so what now I'm going to be doing is actually coming to the login button and what I'm going to be doing here is basically implementing the functionality of what happens when we click on login so that we validate our form so what I'm going to do now is come to login button go to the onpressed call back function and here the first thing that I want to do when the user clicks login is make sure that there's something in the form well to do this the first thing that I'm going to going to be doing is using an if statement where I'm going to say if and then I'm going to do login form key do current state so I access the current state of the login form and then we're going to call validate like so and validate is going to return to us a Boolean value and if you hover over the error that you're seeing it says us that the method validate can't be unconditionally invoked because the receiver can be null and the reason it's giving us this error because it's telling us that current state can have a value cannot have a value as you can see it's giving us a generic type here and saying that this is an optional variable means that current state might have a value might not have a value so what we can do to actually get rid of this error is use a null ofare access operator but just tacking on a question mark before validate so what's this basically going to do is that it's going to say that hey if current state exists then call the validate function on this but now it's going to give us another are saying that a nullable expression can't be used as a condition and the reason for this is because this actual condition now or expression I should say is going to most probably return null if the state doesn't exist or it might return a value but this always needs to return some kind of a value for the if statement to work so what I'm going to be doing here is then again using a null aare operator and I'm going to say like so false so what this is basically saying is that if the Val Val function returns a null value then we're just going to use false otherwise we just use the value that gets returned by the validate function so that's pretty much all we have to do so with this we can do command save and we can just leave this and we can come back to our actual app and click on login and as we can see nothing's happening and the reason for that is because even though now we are calling the validate function on our forms key and we've attached our key to our form we haven't implemented the the actual validation logic that needs to run when we call validate so this validation logic needs to be implemented for each of the fields so in this case I need to implement some validation Logic for the username and then some validation Logic for the password so to implement the validation Logic on our text form field or any form field we have a validator function callback where basically we are given a value and then this function determines if the value that's provided to us and this value comes from the actual inputed stuff that the user inputs within the text form field is the value valid or not so here we can perform any type of validation that I'd like to do so in my case the actual validation I want to do is make sure that the value is not null so I'm going to do if the value is equals to null or the value is empty then what we do is that we return a string which says enter a username like so otherwise we do not return anything thing as you can see so what this basically means and as you can see what the validator function expects from us is an optional string if the actual return value from our validator function returns an actual value this means that the validation has failed and if we do not return anything that means that the actual validation has passed so in our case if the value is null or the value is empty then our validation fails because we return enter username otherwise it doesn't so now with this done I'll take this I'll copy this if statement I'll come to the actual text form field I'll create the validator function call back here as well and then I'm going to add the same if Clause within this but instead of doing value do is empty I'm going to say if the value's length is less than five then we say enter a valid password like so and do command save so with this done now we've successfully implemented the validation logic as well so if I go back to my application Press login you're going to see see that now when we Press login we call the validate function or forms key which is attached to this form and since these text form field widgets are children for this form this form automatically calls the validator functions on all of these form fields and this form is only going to be valid when all of the validator functions for all of the form fields that we include within this form actually do not return a value and have valid values within them so if I add a username let's just say like so and I press login you're going to see that now the username error is removed but we need to enter a password as well so let's enter a password 1 2 3 4 5 Press login and you can see that the errors are gone one thing that I'd like to quickly mention here is that for my password field I'd like to make sure that I obscure the text so how can we do this well for the password field what I can do is actually on the text form field there's a property called oxp text and I'm going to set this to true and do command save and this will basically OB the text and we won't be able to see it anymore so now that the validation is working we can move on to the next step which is to actually save the information from these fields into a variable that we can then use later to actually send our request well the logic is going to be pretty similar to how we did for validate if we made sure that our form was valid then what we can do is actually on my login form I can go to the current state and on that I can optionally call the save function and do command save so now if the form is valid and we press on login it's going to call this function as well and what save is basically going to do is that again for the form on every text form field or any form field I should say we have a function called on saved and this gets called when we call it save function on the key and here we are given a value and this is the value that's within the form field when the actual save function is called so here what I want to do is basically save this value now within an actual variable so firstly we need to create a variable then so let's go to the top of my login page State class and here what I'm going to be doing is now creating a string variable and I'm going to say this is going to be an optional string variable and the reason for that is because we might have a username we might have no username given to us so like so so the username might be null or it might have a value same for password then I'll come down to where I have my login form back to the on Saved function and here what I'm going to do is basically say that I'm going to set the username that we've actually created to the value that gets passed in and do command save but if I just do this and click on login even though everything looks to work the way it's supposed to work this is actually not going to work and the reason for that is because when we are working with stateful widgets as you can see there's a certain thing that we have to do in order to update the actual State that's within our stateful widget so in this case this username and password are part of the state of our login page so to update them we can't simply just do username equals to Value what we need to do is actually wrap this within a set State call and then within this we can actually say that username is equals to Value so what set state is basically going to do in a net cell is that it's going to take the value it's going to put that into the username but then it's also going to render a rebuilt of the widget tree or more specifically just the viget tree of this actual login page and this way the value will then be actually persisted and actually the changes will be displayed on the screen as well so always remember when working with stateful widgets that you need to call set State before you update the state for that corresponding stateful widget so let's copy this on Saved function and let's go back to the other text form field and before the validator function let's do the same but this time instead of setting it to the username let's set it to the password and do command save and there we have it that's pretty much done so now what I'm going to do is that I'm going to come down and after my on pressed I'm going to basically do print and within the string I'm going to interpolate the value username and password so to interpolate values within strings we use a dollar sign following that we can use the variable name so username and then I'm going to do a space Dash and then I'm going to do password let's do command save let's open up the debug console so to open it up you can go and click on Terminal New terminal and then basically click on additional views and go to debug console and let's see what happens so let's restart our application and as you can see it's letting me know that the app has restarted if I click on login nothing's going to be printed and you can see that it tells me to enter a username and a password so let's copy this username that we're going to be sending and pasting it in and then I'm also going to do the password come back and paste it in done and if I click on login this time you can see that the validation logic passed and in our debug console we can see that the value for the username was printed following by a space a dash and then the actual password so now we are not only validating the form correctly but we're also saving the information that's within the form into variables that now we can use to actually authenticate ourselves so I'm going to remove this print state for for now and we can do command save and that's pretty much it the last thing that I'd like to do is that for this application only what I want to do is that we are right now testing our application and testing the login functionality is that I want to give a initial value to my text form field so it's easy for me to log in quickly without having to input the username and password all the time so to do this what I'll do is that I'll firstly come to my actual text from field for my username and here I'm going to set the initial value to be the username which dummy Json provides us as a valid username and then the password I'm going to come back and for my other form field which is the password one I'm going to set the initial value to be the password and do command save so now with this if I restart my application by default our text form fields are going to have initial values which are going to correspond to the valid username and valid email now that we have our form working and we have the information from our form being saved within variables the next logical step is to use this information to actually perform the login operation so how are we going to be doing this well to do this the first thing that we need to do is actually send requests over the network and to achieve this we're going to be using the first package that I'm going to be introducing to you within this course and we're only going to be using two and the reason I'm keeping the packages to a minimum is to one make you guys use only the barebone stuff that comes with flutter so you get a good understanding of it and not to confuse you guys too much with all of the packages that we're going to be using but at the same time I want to give you a feel for what it feels like to use packages so I'm going to be showing you a very useful package which is called di which is a very powerful HTTP Network package for Dart and flutter and this is the actual package that I use within all of the projects that I build using flutter and this is a package that I highly recommend and as you can see with 6,000 or so likes that this package is very popular so to use packages what we do is that we basically can find the different packages that we can implement or add to our flutter project on a website called pub. so as you can see if you come to the website it says that it's the official package repository for Dart and flutter apps so here you can see a lot of different packages that other talented developers have created that you can Implement within your FL application to add different kinds of functionality to it such as audio Firebase Clash lytics video players and things like that so to add an actual package what we do is that we navigate to that packages page and then we basically come to where it says the title for the package and we click on this clipboard button then we come back we come to our pspec yaml file and the [Music] popspicemiami dependencies what we do is that we come to the dependency section and then underneath of this flutter tag we add our dependencies here by just adding them on a new line and then doing command save since I have the flutter extension installed it's automatically going to understand that a change happen within my pbsp spec. file analyze it see that I've added a new package and then automatically called flutter pupg which is going to go and grab this packages code and put that within my own flutter project if for some reason this doesn't happen for for you then what you can do is open up the terminal and then once youve opened up the terminal the next thing that you can do is make sure that you're within the folder that's the root of your flutter project like so as you can see this is the root of my flutter project and here you can call the command flutter PPG and this will do the same thing again if you follow the steps that are outlined in my setup instructions for how to set up flutter on Mac OS and windows then you shouldn't have to do this but this this is what you can do if you want to then actually add the packages code within your own flutter project so now with this done what I'll recommend is that you stop debugging your application and you give it a run again to make sure that this time the code for the actual package is also included with your actual flutter code when it's actually launched on the device so I'm going to now minimize the browser and we can come back to how to send this network request so to send our Network request what I'm going to be doing is that in the spirit of keeping my code easily understandable and maintainable I'm going to be breaking it up into different parts I want to create a new folder which I'm going to call services and as the name alludes to this folder is going to hold the different services that we are going to be using within our application and then within the services folder I'm going to create a new file and I'm going to call this _ service do dot so as as you can see this file is going to contain a class which is going to called OD service and this class is basically going to assist us in performing authentication related activities so let's get going so firstly I'll just create a class this is going to be a simple do class I'm going to call this Au service so the next thing I want to do now is make sure that during the life cycle of my flutter application that there only ever exists one single instance of our all service class and this is called the Singleton pattern now there are other ways you can do this such as using service located packages such as get it but that's too complicated what we're going to be doing is using the bare minimum things so what we're going to be doing is using just pure dot code to create functionality within our class that limits it to just being a singl ton class so how do we do that well the first thing that I'm going to be doing is that I'm going to be adding a static variable to my odd service class it's going to be final it's going to be of type odd service it's going to be called underscore Singleton like so and I'm going to set this equal to something what am I going to set this equal to well I'm going to set this equal to a call to a factory function so I'm going to Define Factory function by typing in Factory I'm going to call this OD service like so nothing within the parenthesis and then I'm going to say that we are going to return underscore Singleton like so so when the Constructor for the odd service class is called it's going to return the Singleton instance on the class and then I'm going to set the Singleton to odd service Dot and then I'm going to doore internal like so and then to fix this error all I'm going to be doing is actually coming down and saying that we are going to have a Constructor which is going to be the following and do command save and that's pretty much all we had to do so now with this done this class is only going to ever have a single instance of it available to to us to use during the life cycle of our application and we won't be able to create multiple instances of our o service so the last thing I'm going to be doing now is that I'm going to be creating a function on my odd service and I'm going to say that this function will return a future boo so this function is going to take some time to complete and once it completes it's going to return a Boolean value to us it's going to be called login it's going to take in two parameters one is going to be string username and the other is going to be string password like so and for now the body of this is going to be empty the only thing I'll do is Mark this function as a sync and then for now what I'll do is return false to fix all of the errors then what we'll do is actually go back to our login page and here what I'm going to be doing is coming back to our login button and after we've made sure that our form is valid and we've saved it the next thing I'm going to be doing is creating a variable called bu type result and setting it equal to Au service which we're going to import from our services folder and then I'm going to do Dot and I'm going to call the login function like so and here we're going to be passing the username and password and that's pretty much it the only thing that now we have to make sure is that it tells me that a value of type future B which is the value that this login function returns can't be assigned to a variable that expects a Boolean value so to fix this I'll say that this function is going to be a synchronous and then I'm going to await so what A's basically going to do is that it's going to wait for this actual function call to complete and then take the output and put that within result and then to fix these errors with the username and the password you can add exclamation marks after the username and the password letting the actual do compiler know that you know for sure that even though username name and password are optional string time variables that they for sure are going to have a value and the reason we can do this with certainty is because we're already making sure with our own Logic the username and password are never null so let's do this let's go back to our OD service and then let's print username password to the console um and let's just print username uh open up the terminal go to the debug console and then restart my application and then if I click on login you can see that it's printing the username so now that we are correctly calling the login function the next thing that we need to do is actually send a request to the specific endpoint how can we do this what I'm going to be doing is creating a new service within my services folder called HTTP Service as the name alludes to this service is going to allow us to to send HTTP requests and then what I'm going to do is basically come to my OD service copy all of this stuff come back to my HTTP service paste it and then I'm just going to say that I'm going to rename the symbol and instead of this being odd service what I'm going to do is say this is going to be HTTP service class like so and then what I'm going to be doing is basically removing the login function from the HTTP service class and the reason I did this was to one save time and two that I also want just single instance of the HTTP service available to my application during the life cycle of it so within here what I'm going to be doing is actually firstly setting up the do object so that we can use it to actually send HTTP requests I'm going to create a function which will return a future void I'm going to say it's going to be call setup and the setup function will optionally take a named parameter which is going to be called Bearer token so this is an optional argument which is a named argument that might get passed to the setup function but it's not required and then I'm going to mark my function as async and open up its body and do command save the next thing that I'm going to be doing is that I'm going to be coming to my HTTP Services internal Constructor and here I'm going to say that when the HTTP service gets constructed I want to call the setup function like so and the last thing that I'm going to be doing is that I'm going to be adding a variable to my HTTP service class called undor Deo and I'm going to set this to a new instance of do like so and do command save so now with this done let's actually go to our dummy jason.com doog page and let's see what type of information we need to send so we need to send a post request to// login with the following headers and and the following body to be able to successfully authenticate ourselves with the API so I need to set the specific headers within my request for this to work correctly so how will I do that well firstly I'll again come back to my HTTP service class and when setup gets called what I'm going to be doing is creating a variable within this called headers and I'm going to set this equal to a map here I'm going to say that the only header that we're going to be setting is going to be content type like so and I'm going to set that to application SL Json so this is what the actual API instructed us to do or the docs I should say instructed us to do once this is done the next thing that I'm going to be doing is telling do that hey you need to use these headers so how do we do that well I'm going to create a final variable I'm going to call this options and I'm going to set this equal to a new instance of Base options and then what I'm going to be doing here is that I'm going to set the headers to headers like so and do command save so this is basically going to for these options set the headers to be the headers that we've specified and the final thing that I'm going to be doing is that I'm going to access the do variable and I'm going to say that the options are going to be equal to the options that we have just defined and command save and there we have it now we've instructed do these headers when sending a request the next thing that I want to do is also on my base options actually Define the base URL for my API so how can I do that well within my lip folder and this is just for the sake of making my code be as maintainable as possible I'm going to create a new file and I'm going to call this conar Dot and within constar dot I'm going to create a variable which is going to be a constant it's going to be called apore basore URL it's going to be set to https Colon sl/ D jason.com so the base URL to access our API up till here and then all of the other endpoints can be tagged to it to go to specific resources within my API and then what I'm going to do is just make sure that I save this come back to my HTTP service go to the base URL and set this equal to that variable that I just defined called API based URL that we are going to get from the const file and that's pretty much much all we had to do so now one last thing that I'd like to do is make sure that on validate status and you can just paste this in um what I'm writing here but make sure that I tell the that if the status is null then what I want to do is return false otherwise we return status less than 500 so this is something that you should just do for now do not need to worry about what this is actually doing this has something to do with HTTP status codes and making sure the do doesn't throw um actual exceptions when it gets status codes that are less than 500 but for now just leave it don't confuse yourself just put this here and this is going to save you a lot of hassle when the API sends you response codes that are not 200 response codes so with this done that's pretty much it so we've now defined our options and we've told do that hey you're going to use these options with every request that you sent so now we're all good to go so let's let's give a restart to our application to make sure that nothing's broken and we can move onwards to The Next Step so the next step is that I want to create a function that can help us to send post requests to a specific endpoint for our API so how do I do that well what I'm going to be doing is creating a function within my HTTP service I'm going to say that this function will return a future response and we might get a response we might not so I'll say that this is going to be optional I'll call this function post and I'll say that we require two things we require a path to where we want to send the post request to as well as the data that we want to send along our post request then I'm going to say that this is going to be async open up the functions body add a TR cach block and within the actual cach block I'm just going to say that print error like so then within the tri block I'm going to do final response equals to and I'm going to do await undor Doo and then on this we can call a function called post and it requires us to pass it a path which we're already doing but besides this for the data property I'm going to say that we're going to send the data that gets passed to us within this function and command save then that's pretty much all we had to do so now I can come back to my OD service and I can actually use the HTTP service here so I'm going to come to the top of my OD service and here I'm going to say that I'm going to create a variable final HTTP service and I'm going to set this equal to http service Serv like so and do command save then within the login what I'm going to be doing is that instead of returning false um I'm going to remove everything that's here and I'm going to add a TR catch block and within catch what we are going to do is just print error and if we reach the very end of this function I'm just going to return false because we weren't able to log in and within try what I'm going to do is that I'm going to say that we're going to create a variable response and I'm going to set it equal to await HTTP service and we'll call the Post function on it then we have to give it the path you can see that here it tells me that I basically need to send a request to au/ login so let's copy that come back and past it in here for the path and then what's the data well the data needs to be username and password so I'm going to say that we are going to set the username key within our map to username and then the password key within our actual map to password like so and then once this is done that's pretty much all we had to do so for now what we can do is actually print the response dot status code to our console and you can see that it tells me that it can't be unconditionally um access to we can add an elev operator and there we have it we're all good to go so now with this done let's come back to our login page and let's see that okay we are calling alt service. login everything seems to be looking great so the last thing that I'll do is that I will come to where it says login after the response and make sure that I have print so we are now ready to test so I'll come and I will click on login and you can see that after some time we get null printed to the actual console so why is that well the reason for that is because in our HTTP service I made a silly mistake where once we actually send the request um we are not returning the response so let's return the response do command save and come back restart our application and now if we click on log in you're going to see that it returns 200 to us so a 200 status code means that our request was successful so we can continue onwards implementing the logic for what happens when the request is successful so what I want to do is that once we get a response back I want to make sure that the responses status code is 200 like so and our response data is not null then I'll open up the body for this if clause and here what I'm going to do is print response. data and that's pretty much it uh and I can add a ex nare aess operator here as well um to command save and then we can restart our application and Press login you can see that after some time it prints a bunch of information to us which includes the ID username so this all relates to this information that gets returned to us when a successful request is sent so now what I want to do is that I want to take this Json that gets given to us and convert that into an actual class or a user class I should say so that I can use that within my application so to the Json that we get from response.data into an actual dot object what I can do is actually come to a website that's called quicktype doio and let me increase the size for this and you can basically open Quick type once you do this what you can do is give your class name in my CL I'm going to give my class name of user I'm going to say that the source type will be Json and then what you can do is come back to the dummy jon.com documentation copy this response come back paste it in here like so and that's pretty much all you had to do and with this done you can see that it automatically creates dot code for us for what the user class should look like but what I'd like to do is also add some actual functionality to this class so that we can pass it an actual map and then it can create a user classes instance for us using that so to do that I'll click on options and I'm going to basically say that I want to generate a copy withd method and then once I've said that I want a copy with method I can also say that I don't want this class to be just types only and this is basically going to add some other useful features to my class that are going to allow me to basically take in an actual map and then return a user objects instance so then what we can do is just copy all of this code like so come back to my actual code go to the lip folder and here I'm going to create a new folder folder now called models within this I'm going to create a new file called user do do and then within this I'm going to paste all of the code that we had generated using quick type and that's pretty much it so now that we've done this what I can do is basically remove all of the stuff that you see at the top here we don't need two of these things um don't need do convert as well and do command save and we can remove these comments as well and then we can come back to our actual a service so within my a service what I want to do is that I want to say that basically if we made sure that our response is correct I want to create a user variable I want to set that equal to a new instance of our user object so how do we do that well firstly I'll come to my OD service and here I'm going to say that my odd service is going to have a variable of type user which is going to be optional we'll import this class obviously from models SL users do Dot and then I'm going to say it's going to be called user like so and then I'm going to say that we're going to be importing this from do/ model user. then I'll come back and I'll say now user is going to be equal to user. fromjson and here I'm going to pass the response. data like so and that's all we had to do so now what happens is that we pass it the map and this Factory function that's on the user class takes in all this map data as you can see and returns a new instance of the user object to us that's pretty much all we had to do so now if I print user to the console and let's open up the debok console once again you can see that if I restart my application click login it's going to print to the console instance of user so basically it's telling us that we are printing to the uh ual debug console and instance of the user object there we go that's pretty much all we had to do and we're actually saving this information within our actual odd Service as well and we'll come back to this later on but this is very cool um so now that this is done the last thing that I want to do is that I want to update my HTTP service and let it know that now that we've authenticated our user that for all the other subsequent requests that we're going to be sending using the HTTP service that I want to include the JWT token that we have received as a response from au/ login within those requests so to do that it's going to be very simple all I'm going to be doing is once I have actually made sure that the user is now going to be having a value I'm going to do HTTP service Dot and I'm going to call the setup function on it again and if you remember correctly what setup basically does is that that it defines the options that do is going to use as well as the headers and then tells di to use these options so I'll come back and I'm going to say that now we're going to call setup but this time we are going to pass a beer token to the setup and this is going to be the user and then specifically the token property on the user like so and that's pretty much all we had to do and do command save and there we have it now everything seems to be working and the final thing I'm going to do is return true and do command save so now with this then we are now actually ready to test the complete login flow so to do that I will come back to my actual loginor page. file come to where the login button is the onpressed call back and then let's see what we get for the result so once we've actually called the login function we wait for it to complete and then we put the actual operations return value into result so let's see what the result is so let's print the result to the console like so and then restart our application and if I keep the username and password the same and Press login you can see that it should return true if I change the username to be incorrect or the password to be incorrect and I press login it's going to return false and everything seems to be working as we had intended to work so now the last thing that we need to do is just basically Implement some kind of a functional within our application that will allow us to actually display a popup to the user or a dialogue I should say which lets the user know if the actual login operation was unsuccessful so to do that what we're going to be doing is actually using a package called status alert and it allows us to basically create these beautiful dialogues pop up on the screen of our actual flutter application to tell the user about something that has happened so let's copy this package and similar to what we've done before let's come back to pope. yaml to the dependency section and after the you paste in status alert and do command save let's make sure the flutter pop get gets called and then stop running our application and then we should start running our application again then once our application is running again all we have to do is basically say that if the result that we get from our actual login operation is true so that means if result then for now we don't do anything else we are going to be doing something well what are we going to be doing well basically what I'll do is that I'll use the status alert package and on that I'll say that status alert. show and then we pass it the context that's one thing that it needs but besides this I'm going to set the duration for the status how long is this popup going to be appearing on the screen if the user doesn't dismiss it I'm going to say it's going to be duration seconds and two so for 2 seconds I want the status alert to be be shown then what I'm going to do is set the title property and this is going to be login failed like so then I'm going to say what the subtitle for this is going to be and that will be please try again and then after this I'll say that the configuration property for this is going to be const icon configuration and I'm going to say that the icon that's going to be displayed for this is going to be icons do error and finally the last thing that I'm going to be doing is setting the max withd property to be 260 and do command save so now with this done I going to restart my application and if I change the username to be something that's incorrect and Press login you're going to see that it tells me login failed please trag in and then it beautifully dismisses so there we have it now we've successfully implemented the comp complete login functionality within our actual recipe book app the next thing we need to do is actually once we made sure that the login was successful is redirect the user to the actual homepage and then we can actually work on the homepage and how the UI for the homepage should look to navigate to the homepage from our login page now that all of the authentication logic has been implemented we have to implement navigation within flutter and the way we're going to be implementing navigation is by by using no package just barebones navigation implementation using whatever tools we have at our disposal using flutter so let's take a look at it so to implement navigation what we're going to be doing is going to our main. do file and here on my main. do file as I had mentioned to you guys at the very top of our budget tree we have a material app our material app if you hover over it provides us an actual property that we can pass to it called Roots which basically Define all of the different pages that we can go go to in our application we're going to be using this property to actually develop some of the navigation Logic for our application so how do we work with roots well the first thing that I'm going to be doing is that I'm going to remove the home property because when we're working with roots we don't use the home property and I'm going to set the roots property to an empty map for now and if I hover over this you're going to see that the actual Roots expect us to basically give it a map and this map basically needs to have strings as it keys and then widget Builder functions as it values so what this basically means is that the key for the route is the actual routes name I should say and then how this route is built is basically defined as a function where we pass the context to this function and then we basically return what the actual rout should look like so if I go to slash login then what I want to do is return the login page so here what I'm going to do that I'm going to set the return value for this function to be equal to a new instance of our login page and since I also want the ability to go to the homepage then what I'm going to be doing is adding another row to here called slome and I'm going to say that we're going to basically get the context pass once again but this time we're going to be returning our homepage but we haven't created our homepage yet so let's quickly create that so to create my homepage what I'm going to be doing is coming to Pages creating a new folder here or a new file I should say call it homepage. doart once I've opened it up here I'm also going to be creating a stateful widget but now I'm going to quickly Breeze through it because you guys already understand how to create stateful Widgets or what the basic skeleton of one is and then I'm going to give my Widget the name of homepage so what I've basically done is that I've quickly created a homepage class which is a stateful widget then I've also created the corresponding homepage State class for the stateful widget then for the build function I am going to be returning a scaffold once again because this is a new page in our application and that's pretty much it now that this is done I'm just going to quickly Define the app bar for my scaold and this is going to be a instance of an AB bar here what I'm going to do is that I'm going to give it a title and the title in this case is going to be a text widget where we are going to say receip book like so and then once this is done I'm going to add the center title property and say that we are going to Center the title and that's pretty much it with this done the last thing that I'll do is that for my scaffold I'll Define the body property and I'm going to say that this is going to be a called the function called it build UI then as we had done before I'll say that I'll create a function which returns a widget it's called underscore build UI and for now it just returns an empty container we'll talk about what container widgets are but let's just do command save and call it a DAT then I'll add a const here because our text widget is not going to be changing I'll close down all of these different files I'll come back to my main. doart and now I'm going to say that for /home root I want to return an instance of our homepage like so and that's pretty much it so with this done I'm going to stop running my application because we're going to get an error if you try to run it right now and before we can start it again I'm going to set the initial root property on the material app to be one of the keys in this Roots map so what I want to do is that when the material app initially loads I want to direct the user to the login page so I'm going to take whatever key that corresponds to the longin page is and pass that as the initial root with this done I will say start debugging once again and this time we have now changed the logic within our material app to not depend on the home property to actually render a page but actually use the roots and the initial root property to determine what page needs to be shown so now that we're using the login page let's go back to our login page and let's see how we can navigate from our login page on a successful login to our homepage so to do this what I'm going to be doing is coming back to my login button then the elevated button and onpressed call back here when we were basically checking if the result for our actual login operation is a success or true I should say then what I want to do is navigate to my actual homepage so how do we do that well basically we are going to use the Navigator object and then on that we have a function that's called push replacement name and the reason I'm using push replacement names is that it's basically going to replace the current screen with the new screen that we pass here and it's not going to allow the user to go back so it's going to entirely remove the current screen and replace it with the new screen without giving the user the ability to go back to the login page because I don't want that I want the user to log in then move on to the home page I don't want them to have the ability to come back and then here what I'm going to do is pass the name of the the root so if you remember correctly for our homepage the name for the root was /home so that's why I've added it here like so and that's pretty much it so the last thing that I want to do before we just test this out is actually go to my services folder and then my HTTP service and I just want to make one thing that we forgot to do and that was that I want to basically to the headers add our beer token as well because we weren't doing that before so we are now going to get past a beer token if we log in and we get a token returned to us and then we call setup again and then I want to update the headers so what I want to do here now is basically Implement logic so that the beer token is included within the headers if we pass it so how can we do that well it's basically going to be very simple I'll just have a if statement where I'm going to say if the bear token is not equals to null then what I want to do is that to my headers I want to set the authorization header to be the following and it's going to be equal to this string where it's going to be be space and then I'm going to interpolate the Token within the string by doing dollar sign Bearer token and this is just an industry standard way of working with JWT token where in our request header we need to add a authorization header and the value for that is Bearer splash the actual Bearer token so with this done let's do command say we're now good to go everything's working as intended so hopefully fingers crossed if I click and log in and the operation is a success we are taken to our homepage as you can see and now we can actually start working on building the UI for our homepage so before we begin start building the UI I think it's good for us to actually take a look at the design for our actual homepage so let's open up the screenshot and let's see what's going on so at the very top we have our app bar which has a title which we've already implemented and then below that we have these buttons that we can use to actually filter through the actual recipes that are shown to us below which we have a list view that's showing all of the recipes to us so let's implement the top part first which are all of these buttons that we can scroll through to select the meal types and then we'll come to the list view so to work with this what I'm going to be doing is coming to my homeor page. file and I'm going to come to the build UI function the first thing that I'm going to make sure is that I'm going to basically refactor and wrap my build UI function with a safe are widget just to make sure that my UI is always visible and then we can move on to the build UI function within build UI I'm going to be using a container and to my container I'm going to be passing a child and this child is going to be a column and the reason it's going to be a column is because at the top we have this actual scrollable list of buttons that we can use to actually select our meal types and then below that we have a list view so these are two different widgets and to align widgets in a vertical fashion we use a column as I had shown you you guys on the login page as well so let's add a column widget and then once we've added a column widget let's add a children property to that and for now the children's list is empty then what I'm going to be doing is that I'm going to be basically creating a new function which returns a widget and I'm going to give my function a name which says undor receip type buttons and then I'm going to open this up here what I'm going to be doing is that I'm going to be returning a sized box widget like so and before I continue with this I'm going to take this function and I'm going to add this to the children's list for my column and then for the size box what I'm going to be doing is setting the height to be 5% the height of the screen by doing what we were doing before using the media cury now that this is done I'm going to come and say that the child for this actual sized box is going to be a widget called a list View and as the name implies a list view is basically used to show a list of different different widgets that we can scroll through to the user so as you can see if I go back to the design we have the scrollable list of buttons that's why we're going to be now using a list View and then we're going to modify some parameters of this to actually allow us to horizontally scroll the list view so let's come back to our list View and let's see what we're going to be doing here so the first thing that I'm going to be doing is that I'm going to change the scroll direction for my list view to be axis. horizontal and the reason I'm doing this is because I want my list view to be horizontally scrollable not vertically scrollable and then similar to how a column work a list view also as a list of children so what are the actual elements or the widgets I should say that are going to live within this list view so what I'm going to be doing now is that I'm going to basically say that I'm going to have a filled button and this is another button widget that is provided to us similar to how we used a button widget inside of our login button on on our login page called elevated button another button time that we have is called a filled button once I have defined the filled button the next thing that I'm going to be doing is that for the onpressed property so what happens when this button is pressed I'm going to leave that to be empty for now and then for the child of this I'm going to say that I'm going to have a constant text widget and for now it's going to say the following and that's going to be snack like so and do command and save and then I'm just going to add the remaining trailing commas just to make sure that everything looks good and as you can see now we have a fill button that is appearing and we can click on it I'm also going to add before the snack the carrot Emoji then a space then snack just so that it looks a bit nice and then the last thing that I'm going to be doing is that on my fill button I'm going to be basically wrapping that with a padding widget I want to give some padding to my actual field button so I I'm going to say that we're going to have a padding widget and then padding is going to be const and then I'm going to do the following padding I want to add padding which is going to be Edge inserts. symmetric which basically means that I want to add the same amount of padding on the horizontal axis so that means on the left and right which needs to be 5.0 so 5.0 on the right 5. on the left that's why I've used the following padding property and there we go now our button is being shown to us so now what I'm going to be doing is basically I'll copy this padding widget I'll paste it once again because we are going to have another button for breakfast then one for lunch and one for dinner so I need to paste it once more and then once more making sure that all of these actual filled buttons are within the children's list and do command save and there we go we are now seeing all of these buttons and we can scroll through them horizontally because we're using a list view so if we we were using a row this wouldn't be possible because we're using a list view we have the ability to scroll through them and I'll come back to what a row is but for now I just wanted to let you know if you guys were confused as to why we didn't use a row so if you want to make our actual list scrollable then we need to use a list view now that this is done I'm just going to quickly change the actual text on each of these buttons so for the next one it needs to be breakfast then after that the next one needs to be lunch so let's do that and then the one after that needs to be dinner so let's do that as well there we have it now we have stack breakfast lunch and dinner and everything looks great so now that this is done we can move on to the next step and the next step entails actually pulling information from the API and then displaying these different recipes in a list view so how are we going to be doing that well first things first what we can do is actually go to our API and actually see how the data is return to us and where we're getting this data from on dummy jason.com I'm going to come to the sidebar I'm going to scroll and I'm going to go to an endpoint which basically says get recipes by meal type so once I come here you're going to see that we can send a request to the following endpoint and then it's going to return an output similar to this to us what I want to do for now is skip the meal type property and we're going to come to how we can filter the actual data that comes to us from the API later on what for now I want to do is just grab all of the recipes that are on the actual API so to do that we're just going to be using the following endpoint uptail / recipes forward slash so if I copy this and I come back and I open up a new window on Google Chrome paste it in and press enter as you can see this is the data that gets return to us we get a Json object where we have the recipes key for that we have a list and in that list we have a bunch of objects Each of which relate to a single recipe and this includes all of the information for the recipe such as the ID the name what the actual ingredients for it are um and a whole bunch of other things like that so now what I'm going to be doing is that I'm just going to be basically copying how one of these recipe objects look so I can see that there's an actual curly bracket here so this is the beginning of our object and then it basically ends somewhere here like so so I'm going to copy this then what I'll do is that I am going to be going back to the same website which was quick type. for/ doart which we use to actually generate class for our user and the reason we're doing this is because I want to make it easy for us to actually ingest Json from the API and then convert them into actual object objects that we can interact with so that's why we're actually creating the class first and here I'm going to say that the name for my actual class and let me increase the size is going to be recipe and then the Json for that is going to be this so I pasted that in and then I'm going to say that it's going to make sure that I generate the copy with method make sure that null safety is on and types only we just do not select that and this is going to create all of the code that I need for my recipe class for me to take in a Json object and then return an instance of a recipe object I just copy this then I will come back to my actual code in the models folder I'm going to create a new file and this time I'm going to call it recipe. and press enter and then I'm going to paste all of the stuff here and do command save then at the very top we can remove all of the stuff for the functions uh including dot convert and everything like that and just leave the class and there we have it we have now done this so the next step in the process is to now Implement some kind of a mechanism within our application so that we can get data from our API so how do we do that well what I'm going to do is that I'm going to do the same thing that I've been doing before where I'm going to create a service that will allow me to get data from the API and I'm going to call the service data service so I'm going to create a new service in a file called dataor service and then I'm going to say it's going to be dot dott once this is done I'm going to basically create a class and I'm going to say this is going to be our data service class like so and then open it up within this since I want the data service class to also have a Singleton instance what I'm going to be doing is doing the same thing that I've done with the OD service and HTTP service where firstly I'm going to define a static variable of data service on my actual data service class and then what I'm going to be doing after that is just defining the factory function for the data service and then finally just defining the internal Constructor like so just to ensure that there always exists only a single instance of the data service within my application with this done I'm now going to be defining a function on the data service which will allow me to get recipes so for now this function will return a future and the future will be a list of recipe and this recipe class is going to come from the class that we had just created we might fail fetching the data so this is going to be optional we might get the data we might not depends on whether we have an internet connection or we are sending the correct request and I'm going to call this function get recipes then I'm going to say that the actual parameter that gets passed to this function for now are nothing it's an asynchronous function and then I open up the function body the actual URL where we're going to be sending the request to where I should say path is going to be equal to recipes forward slash and the reason we're just doing recipes forward slash is because within do we've already specified the api's base URL so the base URL if I open up the actual documentation again is going to be up till the point which is dummy jason.com so then after that we just need to go to the recipes forward slash endpoint so that's why I've said that the path is going to be recipes forward slash and then after this what I'm going to do is use my HTTP service to send the request so let's firstly import our HTTP service in so I'm going to create a variable on my data service I'm going to say it's going to be final type HTTP servicecore HTTP service and set it to http service like so once this is done I'll do command save make sure that nothing gets broken come back to get recipes and here what we can do is create a variable called War response and set this equal to a a call to send a get request but if I go to my HTTP service for now we don't have a function for sending get requests we have a function for sending post requests but not get so let's update our actual HTTP service so to do that I'm just basically going to be saying the following I'll have a function which will return a future this future will be of type response optional it's going to be get we're going to pass it a path it's going to be a synchronous and then I'm going to open the function body then I'm going to add a TR catch block within catch what I'm going to be doing is just printing the error and if we reach the very end of this function I'm just going to return null and then within the tri block this is what we're going to do we'll create a variable final response set that equal to a waitor do Dot and then I'm going to do get and get I'm going to basically pass it the path like so and that's pretty much it and with that I'm just is going to say that we're going to return the response and there we have it our get function has now been defined so now you can see the actual power of breaking our code down into different Services pages and models and it's making our code easily readable and we're following the dry principle which is don't repeat yourself and this is one of the reasons why I opted for going the longer route in this actual tutorial but actually making sure that you learn good practices and good development habits so that you become not only a competent flutter developer but somebody who also has good programming practices so then I will come back to my data service and now I'm going to access my HTTP service by doing underscore HTTP service and then Dot and I'm going to call the get function and here I'll pass the path like so and then do not forget to make sure that you actually await this actual function so I'm going to do await HTTP service. get then what I'm going to do is I'm going to make sure that the response status code is equals to 200 and the responses data is not equals to null so if that is the case then what we can do is actually for now just print response. data like so and that's pretty much all I'm going to be doing and I'm going to add an exclamation mark here because I know the data is going to be present now we can come back to our homepage and within our homepage we can actually see how we can work with this now data service that we've defined to actually get our data so to get the data what I'm going to be doing is firstly I'm going to be basically creating a new function within my homepage and this function is going to be called recipes list and this function will return a widget so recipes list like so and then I'll open it up and within this function I'm going to return an expanded widget and the reason I'm returning an expanded widget is because I want the list to take up all of the available space on the screen that's available to it I do not want to define a specific size for this actual widget so an expanded widget basically expands its child to take up all of the space that's available to it and then the child for this is going to be a list view as you can see because we have a list view that we can use to scroll through the different recipes but if I just Implement a list View and I'll show you what happens like so we need to give it a list of children but where do we get this list of children from where do we get the data from how do we link the data with the list view is that making sense well if we go back to a data service and if you take a look at our get recipes function I see that it returns a future but flutter conveniently provides us with a widget called the future Builder that allows us to ingest Futures in and then using those Futures build our widgets so how do we do that well the first thing that I'm going to be doing is that I'll remove this list view for your guys's easy understanding so let's remove it and the child for this expanded widget is going to be a future Builder like so our future Builder is going to require us to pass it two things one is the actual future so the future in this case is going to be the data service so so let's actually do that data service and then the function on it called get recipes and then the Builder is basically going to be a function that's going to determine how the child for this future Builder is going to be built and the Builder is going to take in two things it's going to take in a build context and it's going to take in a snapshot and these will be the things that are going to be passed to us and then the Builder expects us to return a widget so what I'm going to be doing for now is just returning a container and then we'll come back to how we can actually work with the list view a bit more but for now let's just return a container do command save and now what's going to happen is that our future Builder is basically going to run this future and then once this future gets resolved or while it is being resolved it's going to call this Builder function and then basically return some kind of a widget back so what I want to do now is basically open up the debug console and kind of show you guys that the actual function is being run so if I go to my debug console restart my application we are going to show the login page click login and if we come to our actual homepage we're going to see that nothing is printed to the console and the reason is because we're not using the recipes list function so let's go to the very top build UI function column after the recipe types button let's add the recipes list to command save and this time if I do this as you can see something gets printed to a debug console and these are all of the different recipes you can see all of the different recipes being printed so this means that our data service function is being called by our future Builder so now we can come to our data service and actually code the remaining logic within the get recipes function so now what I want to do is make sure that this function returns a list of recipes if everything works out the way it should so I'm going to create a variable which is going to be a list it's going to be called a data it's going to be equal to the response. data and then on that specifically I want to access the recipes like so and then once this is done I'm going to now convert this actual say map in this case into a list of recipe so how do I do that well I'm going to create a list of type recipe this is going to be a variable called recipes I'm going to set that equal to data do map so we're basically basically going to take all of the values that exist within our data list and for each of them we are basically going to transform them into a recipe object by doing recipe. fromjson and passing it the element that gets passed to us and then finally once this is done I'm going to cast this to a list like so so what this is going to do is that it's basically going to go through each of the elements that are within our list and then it's going to convert them into a recipe object and then we'll basically get a iterable return back to us as you can see so I'm going to cast that iterable to a list to fix any errors and that's pretty much it so now we have our recipes list created so the final thing I'm going to do is return the recipes like so and do command save but before I do that I'm also going to print the recipes to the console because I want to show you guys something and if I restart my application log in you're going to see that in our console after some time we're going to get an output where we're going to say that there's a list which has instance of recipe objects within it so you can see how now we have these recipe objects available to us and we can use these later on you guys are going to see how this is going to make our life much easier so now that this is done we can go back to our future Builder and see what we need to do there so our future is going to take some time to resolve because this is a network request we're going to send some information to the API and then we'll wait for the API to respond back to us when something is happening and we do not have the data ready what I want to do is actually basically show a loading indicator so how can I do that well to do that what I'll do is that I will basically inside of the Builder say that if the snapshot. connection state is equal to connection state. waiting like so then what I want to do is that I want to return a circular progress indicator widget like so and do command save so you can see that the circular progress indicator was shown to us and then to fix it styling and put it in the center I'm going to wrap this with a widget and this is going to be a center widget so a center widget puts its child within the center of its parent and do command save and there we go now we're seeing this circular progress indicator in the center like so then what I'm going to to be doing is that I'm going to be adding another if statement where I say that if the snapshot has error if an error occurred during the resolution of our future then what I want to do is that I'm going to return a center widget which is going to have a child and this time the child is going to be a text widget that I'll just copy and paste in which is going to say unable to load data and there we have it so if our snapshot's connection state is not waiting and our snapshot doesn't have error that basically means that most probably we now have the data and we can show it so now what I want to do is that instead of returning a container I'm going to return a list view but this time we're not going to be using the default list view Constructor we're going to be using the list view. Builder function and the reason we're going to be doing this is because this is going to allow us to programmatically create our list view so our list view. Builder is going to expect us to pass it in item Builder property which is a function which basically defines how each of the children within our list view are built and this basic function gets two things p to it a context m&n index and what this index is we'll be explained to you in just a bit the index basically refers to the actual item that is being built and this links to the actual property on the list view Builder called an item count so this basically refers to how many items are there going to be within our list view well in our case the amount of items we want to show within our list view is going to be the snapshot that gets passed to us and then the data property on it which is going to be a list of recipes and then the length property on that like so and I can add an exclamation mark because I am sure that there is going to be data available to us like so and do command save so now with this done within my item Builder what type of a widget am I going to be returning well there's a very handy dandy convenient widget that flutter already provides us to display data within a list view called a list tile so we are going to be using that so I'm going to say we will return a list tile like so and do command save and now we are not going to be seeing anything but as soon as I come to my list T and I say that the title property for this list T is going to be a text widget and the text here is going to be the actual specific recipe that is being rendered so how do we know what recipe is this list tile going to be for well I have the index passed to me so what I can do is I can create a variable of type recipe call it recipe and this is going to be the specific item in the snapshot. datal list at the specific index that gets passed to me and then I can use this recipe and access its title like so by doing recipe and then I am going to do name and this is the reason why I opted for converting the map to an actual list of recipes object so that we have intellisense available to us and it makes our coding much easier and it's also going to make sure that we write much less error prone code because the probability of us writing something that doesn't work gets reduced a lot if I do command save now you're going to see that once it loads all of the data it displays all of that to me here and I can scroll through this list view as you can see so now all we have to do is basically make the list tile look as pretty as it looks on the actual screenshots and then we should be almost done with our homepage so let's do that so firstly what I'm going to do is I'm going to set the is3 line property on my list TI to be true then after that I'm going to add the subtitle property and for now I'll stop running my application to avoid this error and the subtitle property is going to be a text widget like so the text here is going to be two things if I show you guys the actual design it's going to be the actual Cuisine type and then the difficulty so let's add that so what I'm going to do is use a string within that I'm going to interpolate first the recipes actual Cuisine and then I'm going to go onto a new line so to break onto a new line I'm going to use back sln this basically means a new line and then I'm going to say that the difficulty is going to be difficulty like so and then a colon space and then I'm going to interpolate the recipe's difficulty like so and that's pretty much it so now I'll do command save and I will run my application again and this time we're going to have a subtitle appearing with the actual recip Kine and difficulty as well so now that our application is running once again let's log in and let's see what happens so now our list tile is showing us the cuisine type as well as the difficulty so the next step in the process is going to be to show this image to show the image what I'm going to be doing is setting the the leading property for my actual list tle and I'm going to say that it's going to be image and as you can see the image widget is used when we want to display image and more specifically I'm going to use the Constructor called image. Network because we are going to be showing an image that's on the network and here we pass it a URL and this URL can come from recipe Dot and then I'm going to do recipe. image and there we have it if I do command save now now you're going to see that the image is being shown to us fantastic so now that we're showing the image the last thing that we need to add to our list tile is this actual text here which shows the rating for the actual recipe so for that what I'll do is that I will come back and I'm going to add a trailing property to my list T it's going to be a text widget and here what I'm going to do is basically interpolate the recipe. rating and then I'm going to convert that to string like so and then after that I'm also going to add a space following that a Star Emoji like so and do command save and there we have it we have the star showing as well I want to increase the text size for this so I'm going to change the styling property for this text to be phone size and then I'm going to do 15 like so command save and there we have it now the size should should be increased and it should look much bigger so the last thing I want to do is basically add some spacing between these list tiles because for now they're bunched together a lot I want to add some spacing between them so for this what we're going to be doing is that we're going to be employing the same Technique we had done before where we're going to be adding some padding to our actual widget on our list tile we already have a property called content padding so we can utilize that and to this I'm going to pass ENT sets and this time I only want to add padding to the top so I'm going to do Ed and sets do only and I'm going to say on the top I want to add 20 pixels command save and there we go now we're just adding to the top 20 pixels and that's pretty much it the last thing that I want to do now on the actual UI design side of things is add some padding to the whole body of my scaffold because it's reaching the extent of the width of our screen so to do that what I'm going to be doing is I'm going to go to the very top to where I have my actual column and if you remember before we had wrapped our column with a container so let's change that to be a padding widget and then let's give it some padding and this is going to be EDG and sets and this time I want the padding to be applied from all four sides so I'm going to do edent sets do all and then 10 pixels from all sides so top right left and bottom and there we we go now we are applying padding and the actual UI elements or the widgets I should say are not being extended to the very edge of the screen and there we have it so with this done we' basically implemented all of the functionality which pertains to the UI so the last thing that we need to do is Implement some kind of a mechanism so that we can actually click on these buttons and then actually filter through these recipes so how are we going to be doing that well if I go to dummy jason.com and then if I come to get recipes by meal type endpoint you can see that if I go to the endpoint which is SL recipes slash meal Das type slash and then here I pass the meal type then it will only return those recipes to me which have the meal type of snack as you can see and if I change this to dinner then it's just going to be dinner recipes so how do we implement this kind of a logic well first thing what I want to do is that I want to track what actual filter is currently active so to do that what I'll do is that I'll come to my homepage come to my homepage State class I'm going to create a variable here I'm going to call this string I'm going to call this meal type filter and initially it's just going to be an empty string once this is done what I'm going to be doing is that I'm going to come to the recipes type buttons and for each of the buttons when they get pressed I'm going to call set state and within set state I'm going to set the meal type filter to be equal to whatever button that was pressed so in the case when we press the snack button I want to set this to snack then I'll just copy this and I'll come to the next one and for breakfast I want to set this to breakfast like so and then for lunch I'm going to set this to lunch and then for dinner I want to set this to dinner once this is done the next thing that I'm going to be doing is going back to my data service and on my data service I'm going to say that now my get recipes function is going to get past a parameter to it which is going to be filter and then what we're going to be doing is basically once we've actually established with our path hit after that I'm going to do is our filter not empty so if our filter is not empty then what I'm going to be doing is that I'm going to be basically appending to the path the following endpoint and that is m-type forward slash and then I'm going to add the filter like so so we're just going to be adding to the actual path the following and then the remaining logic Remains the Same now this path will be used and then the data that gets returned to the API will only be the recipes which conform to the filter that we have defined so let's come back to our homepage now the last thing that I'm going to be doing is coming back to my recipes list to get recipes and here I'm going to pass my meal type filter and then do command save and there we have it all of the logic has now been implemented so the way this is going to work is that every time set state gets called when we click on one of these buttons we not only update what the MU type filter variable is holding but we also because of calling set State cause a widget tree rebuild and what the widget tree gets rebuil built then what happens is that our future Builder calls the data service. getet recipes function with the new meal type filter and then only the recipes that pertain to the filter that we have specified are shown in the list view so now if I do command save we can see that we are seeing all of the recipes as soon as I click on snack it only shows the snacks breakfast only shows us breakfast lunch only shows us lunch so that pretty much concludes all of the functionality for our homepage except for one thing and that is when we click on these list HS we are navigated to our recipe detail page so to navigate to the recipe page from our homepage so that we can view all of the details for our actual recipe I'm going to be doing things a little bit differently than just setting up a route what I want to do is basically pass all of the data to the page and then have the page create itself um and this is going to be a dynamic process so to do this what what we're going to be doing firstly is that we are going to be coming to our homepage and then specifically to the function which is recipes list and here I'm going to be coming to my list view. builder then where I return my list tile now what I'm going to be doing is on that I'm going to be setting a call back function for on tap so basically when we tap on the tile what is going to happen so now if I click on one of these you're going to see that we have this tap animation happening with nothing's happening so now we work towards the logic of actually navigating from our homepage to our recipe detail page so to do that the first thing that we have to do is actually create a recipe page so let's under our Pages create a new file called recipe page. dark and once this is done inside of my recipe page I'm going to be creating a stateless widget class and the reason for that is because our recipe page does not need to manage any kind of state all of the data that it requires will be given to it and then it doesn't need to change anything within itself during the actual life cycle of it so so to create a state L widget all I'm going to do is create a class I'm going to call that recipe page I'm going to say that this is going to extend a state less widget and once this is done I am going to implement the build function within my recipe page and then for now as we have been doing before I'm going to return a scaffold like so and within the scaffold I'm going to set the ab bar property so what do I set the app bar to well this time what I'm going to do is just set the app bar to the following because you already know how appar works and do command save and then the last thing I'm going to be doing is for my scaffold I'm going to set the body property to a function called build UI and then I will come to the actual bottom of my class create the build UI function and then I'm going to say that this is going to return and we will use a column for now which is going to have a children's list which for now is going to be empty and that's pretty much all we had to do so now that this is done our recipe page page requires some information regarding the actual recipe that it needs to display so how do we accomplish that when we navigate to this page well firstly let's actually take a look at what our actual recipe page looks like so it has the image a bunch of details about the recipe and then instructions on how to cook it okay so now if I take a look back at my homepage you are going to see that we basically have access to our recipe object and we can pass this on to a recipe page and then the recipe page can actually use this to display information so to do this we are going to come to our on Tab function and here I'm going to use the function called Navigator do push so the reason I'm using push this time is because I want the ability for the user to navigate back to the page they came from and the way we do that is by using the push method if I used push replacement then we would have completely replaced the homepage and we wouldn't have the ability to come back so that's why we're using portion this is going to put our recipe page in the navigation stack on top of the homepage and then we have to pass it an actual root so this root is going to be a material page root and what this object basically allows us to do is programmatically build our root instead of having to Define them in the actual Roots map on our material app so here the Builder function is going to work similar to how Builder functions have been working in flutter we'll get a context passed to us and then we basically need to return what the route is going to look like so in my case what I'll do is that I'll return an instance of our recipe page and that's pretty much it and do command save so now that this is done if I click on one of these list tiles it's going to navigate me to my recipe page and you can see that since we are actually using an AB bar and we use the push function on the navigator to actually push the recipe page onto the navigation stack we are automatically seeing a button on the app bar that we can use to go back back to the previous page so this is the power of using an app bar and the Navigator object so the next thing I want to do is give the recipe that I want to display the details about to the recipe page so to do that what I'll do is that on my recipe page I am going to create a variable which is going to be of type recipe and then it's going to be called recipe like so and I'm also going to mark this variable as final now that this is done I'm going to basically create the Constructor for my recipe page class and I'm going to say that this is going to get a required named argument which is going to be this. recipe like so and once this is done the next thing that I'm going to be doing is coming back to my homepage to the recipe page where I'm creating it in my material page route and here I'm going to say that the recipe is going to be equal to the recipe that we are accessing from the snapshot data list at the specific index and that's all we had to do so now with this done we can actually close down our homepage because all of the functionality for that is done and go back back to our recipe page and let's actually take a look at what the UI for that is going to look like so on my recipe page I have an image following that I have some text um title prep time and all of the different information regarding the ingredients but if we can kind of take a look at the layout we can actually see that this is actually a column in action so first things first we got to add a column so to do that what I am going to be doing is coming back to my column and we already added it so we can move to the next step so the first step is to actually create a viget which will show the recipe's image so to do that what I'm going to say is that within the column children's list I'm going to have a call to a function called recipe image and then I'll create this function at the bottom and it'll return a widget then within this function I'm going to return a container widget like so this container widget is going to have a height and a width the width will be the complete width of the screen the height will be 40% and we need to pass the build context so let me pass that as a parameter to the function then I need to also add the build context here to the build UI function then where I call my recipe image I'll pass this context and finally where I call build UI I'm going to pass the context like so and do command save so now within my recipe image the next thing that I want to do is that I want to add an image to my container so to do that I'll set the decoration property on my container and this is going to be of type box decoration then on this I can access a property called image and this is going to be the image that I want to display since I want to display an image that is going to be over the network I'm going to use the network image if you were using for example asset images then you would use asset image here so I'm going to do Network image like so and then here we can actually just pass the link to the actual URL for the image so we will get that by doing recipe. image like so and that's pretty much all we had to do so then once this is done it's going to give me an error saying that I can't can't give the network image to the image property on my box decoration and the reason for that is because the image it expects is of type decoration image and then the image property for that is going to be Network image so let's do command save and let's see that the image is being shown to us so that's fantastic now I want to change the fit for the image so that it takes up the complete space of our container so to do that on my decoration image I'm going to have a property called fit and I'm going to set that to be box fit. cover and there we go one more thing that I want to do is that I want this image to basically go behind the actual app bar so to do this I'm going to go back to my scaffold and on my scaffold I'm going to have something that says extend body behind AB bar and I'll set that property to true to command save and now you can see that the image moves up and our actual body for our scaffold is behind our app bar as well so that's great so the next thing that I want to do now is actually create the widget which is going to be responsible for showing us some key details at the top regarding the cuisine how easy it is to create this um the name of the recipe the prep time cook time and things like that so to do this what I'll do is that I will come back again to my build UI function I am going to say that we're going to have a function that's going to be called recipe details and it's going to have the context pass to it like so then what I'll do is that I will come to the bottom of my class and here what I'm going to be doing is basically creating a new function recipe details and then it's going to take in a build context context and then I'll open up the body for this within this I'm going to do the same thing so I'm going to return a container so let me do that the color for the container is going to be colors. white and then after this I'm going to set the width for the container to be the complete width of the actual device once this is done I'm going to add some children to my container and in this case we're going to be using a column column and then I'm going to set the children's list for that to be empty for now and the reason we're using a column is because our recipe details is going to be all of this text which includes some text at the top then the actual title then the prep time and then the reviews so all of this is going to be stacked in a vertical manner so that's why we're using a column so now that this is done what I'm going to be doing is coming to the children's list and here I'm going to add a text widget and I'm going to say that firstly we're going to show the cuisine so to do that I will create a string and within that I'm going to interpolate the recipe Dot and then Cuisine once this is done I am then going to add a comma and after that I'm going to again interpolate within the string the widget the recipe. difficulty and once this is done I'll do command save to see how it looks like and as you can see we can see that it's saying Italian comma easy so we can see both of the things now once this is done I'll just quickly update The Styling for the the text so this time I want to change the phone size and the phone weight like so and then I want to change the actual alignment properties for the children that exist within my column so what I'll do is I'll come to my column and I'll say that we will basically set the main axis size to main access size Max main axis alignment to be main AIS alignment. space evenly and then the cross AIS alignment to be cross axis alignment. start like so once this is done I will also add some padding to the actual column because it's going way too far into the edge of the device so to do that I will set the padding property on the actual container and I'll say it's going to be edent sets. symmetric so vertical means that it's going to be 15 pixels from the top 15 from the bottom and horizontal means 20 from the right and 20 from the left and there we go now it looks much better once this is done I'm basically going to be adding another text widget and this is going to be the recipe's name so I'll do recipe. name and once this is done let's see how it looks so I want to change the styling for this so I'll update The Styling property like so and do command save and there we go now it's looking good once this is done I will copy the first text widget and I will then take it to the bottom and add it after the last one that we had added and this time what I want to do is show the prep time so I'll do prep time and then I will basically say recipe. prep time minutes like so and then after that I'll have a space and I'll say minutes and then once this is done I am going to then have a space and then I'm going to say cook time and the cook time is going to be the recipe then cook time minutes like so and then after this I'll have another space and I'll say minutes and do command save and there we go we can see prep time 20 minutes cook time 15 I'll update the actual phone size to be 15 and then the font weight will be W 300 now that this is done the last thing that I want to do is show the ratings related stuff so I will again copy this text widget I will paste it once more and this time I want to basically show the rating so to show the rating I'm going to do recipe. rating and then do two string and then I am basically going to after this remove the minutes and actually add a Star Emoji here like so and do command save and there we go we can see 4.6 star and then instead of showing the cook time what I'm going to be show are the amount of reviews that this recipe has so to do that what I'm going to be doing is basically where I'm interpolating I'm going to do recipe. review count and I'm going to say instead of minutes it's going to be reviews and there we go and the last thing I'm going to be doing is just changing the phone size to be w500 and it looks amazing now we can see all of the detail relevant to this actual recipe if I go back now and I click on a new one you're going to see that our recipe page is we're going to show details for the recipe that we click on because that's the data that we're passing to it so now we can move on to the next step and that is to actually show the ingredients list so let's do that so the logic for this will remain the same the first thing that we are going to be doing is basically going back to our build UI function and here what I'm going to be doing is adding a call to a new function which I'm going to call underscore recipe ingredients and then we will pass the context to this as well once this is done I will come to the bottom of my class and similarly to what I've been doing before I will create a function which returns a widget called recipe ingredients I'll say that I'll take in build context like so and then once this is done I'll open up the body for this so within the body what I am going to be doing is basically returning a container and then the color for the container is going to be colors. white and let's do command save make sure that nothing's broken then for the width of this it's going to be the complete width of the size of the device and then I'm going to set the same padding as I had done before for the recipe details and then finally what I'm going to be doing is setting the children for this to be a column and the reason we're using a column is because again we are going to be displaying ingredients like so so that's why I'm using a column and the reason I'm not using a list view is because I don't want this list to be scrollable I just want them to be shown not scrollable so that's why we're using a column then for the column what I'm going to basically do is that I'm going to set the children's list and this time what I want to do is dynamically generate this children's list so the way we're going to be doing this is where we'll take our recipe and we'll access the ingredients list on it and then I will map over it and for each of the ingredients that I get so let's do that and then instead of an arrow function let's just use a normal Anonymous function closure I will return a row widget and then for the children of this for now it's going to be an empty list and then finally I will cast this to be a list and this should fix most of the errors for us and I will also add a semicolon here so the reason we're returning a row is because if I take a look at the actual elements that are going to be within my column there's going to be a checkbox following that it's going to be the actual name of the ingredient so that's why we need a row and a row is a viget similar to a column but this time it allows us to embed children within it and it's going to align them in a horizontal manner so the main axis alignment for a row is going to be the horizontal axis and then what I'm going to do here is firstly I'm going to basically add an icon widget so an icon widget can be used to display icons and I'm going to do icons. checkbox and let's do command save to actually see how it looks it looks fantastic and then after this I'm going to basically add a text widget and I'm going to basically show show the ingredient here which we can access by doing I and do command save and now we're seeing the ingredient as well I want to add some spacing between these so what I'm going to do is that I'm going to basically change the text to be a string I'll add a space before I actually interpolate the ingredient within the string this way it should add some space and to command save so now that we're showing the ingredients as well the last thing that I want to show are the instructions for our recipe so to do that what I will do is the same structure that we've been doing before which is I'll come back to the top where I have my build UI I will have my recipe instructions function after the ingredients the context will be passed to this as well and then I will come to the very bottom of my class I will say that we will have a function that will return a widget it's going to be called recipe instructions it's going to get the build context passed to it and then I'll open up its body within this what I'm going to be doing is similar to what I've been doing before return a container so let me copy the code from the to recipe ingredients function and come and paste it here and then the child for this is going to be a column like so and it's going to have a children's list which for now is going to be empty and then I will add the remaining brackets and the semicolon and do command save just to make sure that nothing's broken then since the actual instructions are also going to be dynamic because they might differ depending upon what recipe we're looking at I'm going to do the same logic that I done for the ingredients where for the columns children's list what I'll do is that I will say that I will access the recipe and I will access the instructions on it and then I will map over them and then for each instruction that I get I am going to basically remove this Arrow function create a normal anonos function then cast this to a list so this fixes all of the errors for us here what I'm going to be doing is basically returning a text widget like so and that's pretty much it and then within this text widget I will add the actual instruction and if I do command save now hopefully the instructions should be shown but I want to basically fix the styling of these so let's do that so the first thing that I'm going to be doing is that I'm going to say that each instruction can only take a maximum of three lines and then I want to set the text align property for them to be text align do start and then finally what I'm going to do is set the styling property for my actual text to be const text style and then I will do phone size and I will do 15.0 command save and there we have it and we'll fix this overflow error there's a particular reason for why I wanted to show you this so now this is done the last thing that I'm going to be doing is basically fixing up some of the actual parameters on my column to fix the alignment so the main axis size will be main axis size maximum I want to basically on the main axis align the children from the start so I'll do main axis alignment. start and then for the cross axis alignment I also want to do dot start and this should basically put everything on the left side and that's pretty much it so now the last thing I want to do is fix this bottom overflow error now there are many many different ways in which you can approach these overflow errors and during your flutter development there are going to be many instances where this might pop up and the solution to these depends on the actual context in which you are coding in my case I know for sure that there are going to be situations in which the content that needs to be displayed on the recipe page might extend beyond the total available height to us on the actual mobile device or the actual device that this application is running on so what I want to do is make my body scrollable so that we can scroll through and see more of the content so how can we do that well a good way to do this would be to actually go to the very top where I have my build UI function and before I return my column what I'm going to be doing is basically wrapping my column in a widget and this widget is going to be a single child scroll view so as the name of this widget implies it basically allows us to give it a single child and it makes that child scrollable and as soon as I do this and do command save the actual error that we were getting is now going to be not visible on the screen anymore and if I actually try to scroll the screen you're going to see that now we can actually scroll through our screen and actually scroll through the content of our actual scaffold so this is the reason why I decided to do that so once this is done what we can do now is actually give a proper test run to our application because now we've completed all of the actual functionality so congratulations on making it tus far into the actual video and as always if you want to support me then consider downloading the actual source code for this project a link to that will be down in the description below as well as subscribing to my channel so that you get notified every time I release a new video but let's go back and let's try to actually access another recipe so let's do this shrimp scampy and as you can see all of the information is being displayed to us so one thing that I can see is that for my instructions I want to add some numbers to them so how do I do that well what I can do is actually go back to my actual recipes instruction to the column and then where I'm mapping over the instructions and here for the text widget instead of just showing the instruction I will use a string in this string firstly I'm going to interpolate the index so to do that what I will do is do recipe dot instructions and then do index off the specific instruction that we are showing and do command save so now we are seeing 0 1 2 3 4 5 and six and then after this I will have a space and then I will basically add the actual instruction like so and then after this I'll add a new line as well just to add some spacing between these instructions and I forgot a full stop here so let's do that and there we go now our instructions are looking much better and there are spacing between them so there we go now everything looks the way we anticipated it to be so one final thing I'd like to do is basically stop running this application on the Android simulator and open up an iOS simulator and just test the application of iOS and see if we're getting any kind of issues regarding the actual layout or styling of our application and make sure that the UI looks the same on iOS as well so let's start debugging and once the application is running on the simulator I will resume the video so welcome back everybody as you can see now the application is running on the iOS simulator as well all of the logic looks good if I input a wrong username it tells me login failed if I actually create create the correct username and then Press login it logs me in into the recipe book page the UI looks great I can scroll through everything the filters are working the way we want them to I can click on each of these recipes and it takes me to the recipes actual detail page and everything looks good and there are no actual pixel overflow errors so with that I can say that we can conclude the tutorial here as always if you enjoyed the video then please don't forget to leave a like on the video and subscribe to my channel so that you get notified every time I release a new video and as always stay happy stay healthy keep learning keep going and I'll see you guys guys in the next video bye-bye
Info
Channel: Hussain Mustafa
Views: 2,769
Rating: undefined out of 5
Keywords: flutter crash course, flutter crash course for beginners, flutter tutorial for beginners, flutter rest api tutorial, flutter jwt token, flutter tutorial, flutter, flutter course, flutter full course, learn flutter app development, learn flutter from zero to hero, flutter app development, flutter app project, flutter app development full course, flutter navigation, flutter navigation and routing, flutter developer roadmap, flutter authentication with rest api
Id: 5lDJNFSWUD8
Channel Id: undefined
Length: 150min 19sec (9019 seconds)
Published: Wed Feb 28 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.