Vue.js: Build a Full Stack App With Firebase, Vuex & Vue Router | Chris Dixon | Skillshare

Vue.js: Build a Full Stack App With Firebase, Vuex & Vue Router

Chris Dixon, Web Developer & Online Teacher

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
63 Lessons (5h 35m)
    • 1. Welcome to the course!

      2:32
    • 2. What you will need for this course

      2:48
    • 3. Project setup using the Vue-CLI

      5:29
    • 4. The header component

      10:10
    • 5. Home page component

      9:23
    • 6. Creating the menu component

      9:22
    • 7. Looping through menu items

      6:34
    • 8. Pushing orders to an array

      7:05
    • 9. Adding the shopping basket

      4:33
    • 10. Making the shopping basket dynamic

      5:20
    • 11. Shopping basket methods

      4:33
    • 12. Structuring the admin section

      5:18
    • 13. Listing current orders

      6:16
    • 14. Add new pizza component

      8:32
    • 15. Form input bindings

      5:38
    • 16. Setting up our Firebase database

      8:07
    • 17. Adding the login component

      3:26
    • 18. Enable Firebase authentication

      3:59
    • 19. Signing in and out

      7:30
    • 20. Final components

      5:51
    • 21. Router installation and setup

      3:25
    • 22. Creating our routes

      5:52
    • 23. Router link in more detail

      4:43
    • 24. Binding and dynamic routes

      5:48
    • 25. History and hash modes

      3:15
    • 26. Catch all routes and redirecting

      1:40
    • 27. Nested routes

      5:27
    • 28. Nested router view

      6:09
    • 29. Adding names to routes

      4:25
    • 30. Router navigation methods

      4:40
    • 31. Global navigation guards

      7:03
    • 32. Component guards

      4:27
    • 33. Guarding individual routes

      2:12
    • 34. Defining scroll behavior

      6:46
    • 35. Re-factoring our routes

      2:12
    • 36. Named router views

      9:08
    • 37. What is Vuex?

      3:01
    • 38. Installation and file structure

      4:12
    • 39. Initial state and accessing the store

      4:40
    • 40. Improving store access with getters

      5:09
    • 41. Changing state with mutations

      6:37
    • 42. What are actions?

      2:02
    • 43. Setting the user with actions

      5:51
    • 44. Dispatching actions

      6:54
    • 45. Mapping getters

      3:34
    • 46. Splitting our store into separate files

      6:52
    • 47. Using modules

      9:02
    • 48. Binding Vuex to Firebase

      8:35
    • 49. Sync orders with Firebase

      3:26
    • 50. Displaying orders in the admin section

      8:51
    • 51. Moving add new pizza to the central store

      3:21
    • 52. Removing items from the database

      6:01
    • 53. Hiding the admin from unauthorised users

      3:01
    • 54. Calculating the basket total

      2:51
    • 55. Global currency filter

      4:58
    • 56. Finishing touches

      5:28
    • 57. What is code splitting and lazy loading?

      4:47
    • 58. Lazy loading with the Vue router

      4:20
    • 59. Grouping components into the same chunk

      2:14
    • 60. Lazy loading with conditional rendering

      7:35
    • 61. Firebase rules

      4:24
    • 62. Deploying to Netlify

      7:16
    • 63. Follow me on Skillshare!

      0:23

About This Class

*** Class fully updated for January 2020! ***

If you have a little experience of building websites using Javascript or frameworks such as Vue.js, this course is the next step in your learning journey! 

During this course, you will build a full stack project to push your skills even further and discover how to integrate state management, front end routing, databases, authentication and code splitting.

Finished code is available for each lesson on Github to compare if you get stuck:

https://github.com/chrisdixon161/Pizza-Planet-V2-Stages

============================​

If you do not have any experience of Vue.js or a similar framework, I have a beginner friendly course also available:

Vue.js 2 Academy: Learn Vue Step by Step

============================

You will build a pizza restaurant project from scratch which allows users to place an order from a menu section. These orders are then pushed to Firebase for persistent data storage. 

We also create a admin section, where authorised users can add or remove menu items and manage any orders placed. these orders are also pushed to Firebase.

All of our pages are managed by the Vue Router and you will learn all about creating routes, navigation methods, nav guards, binding routes and different router modes.

This project also uses Vuex for state management. This will give our app a single store for all of our state, this will be also kept in sync with Firebase so we always have easy, local access to all of our data.

So if you are looking for a course to teach you how to build a full, feature packed project from scratch, then enrol today!  

Transcripts

1. Welcome to the course!: Welcome to this course. It's great to have you here. My name is Chris. I'm a web developer and online course creator teaching thousands of students across the world. I have created this course to take all of you-all JavaScript skills to the next level. Here in this course, we will build a full stack application using Vue.js, one of the most popular front end frameworks available today. We will be building a pizza restaurant application where a user can place orders from our restaurant menu. Also, we'll have the facility for the restaurant owner login to an admin section. This section will allow us to add or remove items from our menu, see any current orders, and also remove orders when completed. This project will use the latest Cloud Firestore from Firebase for the back-end of our application, which will be used to store all menu items along with any orders. We will also take advantage of Firebase for authentication too., this will only allow authorized users into our admin section, along with certain security rules too. Also we will keep a local Vuex store in sync with Firebase to manage our application state. This will allow us to access and manage all of the information we need easily in one central place. You will also learn about the Vue Router, which is used to manage navigation between pages in our app. Here, you will learn many concepts such as adding navigation guards and defining scroll behavior to name a few. We even move on to some more advanced concepts, such as lazy loading and code splitting, to make the application load more efficiently. The ideal student for this course will be somebody comfortable building websites with a little JavaScript knowledge, experience of Vue.js, or even another framework or library such as React will be an advantage, although I will try to make things as clear as possible for people new to Vue.js. This course is ideal for students looking to see how everything fits together in a real phone application. By the end of this course, you'll become full building full stack applications using Vue.js and Firebase. Sign up now and I hope to see you in the course. Take your Vue skills to the next level. 2. What you will need for this course: For this course, there are only a few things which you will need, and they are all free to use and download. You probably already have most of them already. First is access to a terminal. If you're using a Mac, you can use a built in terminal. To access this you can use the spotlight search by pressing the command and space key together. Then search by typing in the terminal. If you're using Windows, you can use a program such as the PowerShell, which comes shipped with Windows. You can find this by typing in PowerShell into the Windows search bar. Don't worry if you're not familiar with the terminal. We only need a few commands and we'll do them together when we need to. You will also need a good web text editor. For this course, I'll be using the Visual Studio Code. This also has a built-in terminal, which will make things even easier for us. As we will use a terminal quite a lot during the project. But of course, feel free to choose any which you prefer. We will also need Node.js and npm installed too. These were downloaded from nodejs.org. I already have Node.js installed. If you don't, go ahead and click on the latest version and download for your particular operating system. Downloading Node also installs the latest version of npm2, which is a node package manager used to download JavaScript packages, which we'll use throughout this course. Next up is the Vue CLI. If you go to github.com/vuejs/vue-cli. You can find out some more information about what the Vue CLI is. You will need to download Nodes before doing this, as Node is a requirement for the Vue CLI. The Vue CLI or command line interface, is a tool which allows us to quickly scaffold Vue js applications with a quick terminal command. It has various templates which we can use to create apps from a single HTML page, right fruit complex web pack setups. We'll be using a simple web pack version when a come to this episode. We will cover installing the Vue CLI soon when beginning this project. However, if you want to read through this guide to learn more about the templates, or even go ahead and install. Feel free to do this now, if not, continue on, and we will install this soon. 3. Project setup using the Vue-CLI: I'm going to be creating this project using a view CLI to quickly create our new app. If you've not used the view CLI before, It is a great tool to quickly scaffold out out of application and get up and running with view project really fast. It includes everything we need to run view applications, including it to links such as web pack, and gives us options to install other plug-ins such as bubble and Linda. If you have this already installed, that's great and continue on. If not, you will need to run a command in the terminal to set this up. I'm going to be using the built in terminal with Visual Studio code, and of course you can use a standalone terminal if you prefer. Head over to Visual Studio code. I already have the terminal open at the bottom. If you don't click on the Options at the top of the screen, go to terminal and then new terminal. I'm going to install a view CLI globally, so it's available for all projects and using npm. The command which needs is npm i have install dash g flag, so this is installed globally. Then the package you need is @ vue /cli gave this a few moments to install, and then I'll see you when this is done. With the vue cli now installed we can use this to create our new project inside of the terminal again, I am currently inside of the root user directory. I'm going to use the cd command to change into the desktop. This is where I'm going to add the project. Of course, you can use any location of your choice to stall this project. We can then initialize the project in a terminal using the command view create. Then the name of our project, which I'm going to call the pizza - planet. It entered to create our projects. I'm going to begin with the default bubble and yes lens, hit'' enter''. This will learn install the plugins which is required, so once again, I will come back once this is done. With this now completed, you should now have the project folder on the desktop here. I'm going to go ahead and drag this over into Visual Studio Code, which will automatically detect the new file path photos and add this inside the terminal. Meaning we don't need to change directories into this new folder and once again, I'm going to open up the terminal since this has restarted, we in the pizza planet folder. All we need to do now is to start off our development server using the command npm, run serve. Let's start this off. I'm also going to open up the browser where we can access this using our local host. We can see here our local host is running on port 8080, so I'm going to command or control click on this, then open this up inside of the browser. This is the default view we see when using view CLI and if you see this page, everything is working fine. I'm going to go into the source directory wherever vue files are stored, and then go into the main app vue and just do a little bit of clean-up work with this file. I'm going to remove the image and the HelloWorld components. We can also remove this Helloworld component since we'll be creating our own and also the HelloWorld reference from our vue instance. This div inside of our template is where we can add any content which you want to appear inside of our app. Let's begin by adding "p" elements. Then inside here we can simply say hello, save this file and head over to the browser and any changes are automatically updated. Next, I'm going to add the images to our assets folder, so these already when we need them. The images have been provided with this course, and I have these available on the desktop. You can of course, use a different set of images if you prefer, or follow along with the exact ones which I'm using. Let's open up the side bar and head over to our assets, which are inside the source. We can grab the images folder and drag this over inside here, and all of our images are now available when we need them. We of course need a components folder to and this is now automatically created photos when using the vue CLI. To begin, I'm going to add some components which are going to be a single files. Let's click on components, add a new file, and the first one is going to be the Home.vue. The second one is going to be photo Header.vue. We can also remove the HelloWorld example by the deleting. Since we don't need this for our project, we have this in place. Let's move on to the next video, where we'll begin to add some content to these new components. 4. The header component: I'm going to get started with the header components which we created in the last video, which will have our logo, our site title, along with some links to other pages. Inside of this Header.vue, let's begin by creating our template, which is going to contain a header elements. At the top of our header we're going to have a div, which is going to be a rapper bubble logo, and also our site title. We can add a class to our div. We can link this to the CSS in just a moment of header logo. Inside here, the first thing I'm going to do is to add our image and the image which is being included inside of the assets on the images folder, is going to be for the planet.jpg, so I'm going to link this. This is from the../ slash assets, the images folder and the name of planet.jpg. As the old text I'm going to add a pizza planet icon, followed by a level one heading, which is going to link to our homepage. We can add the href as a forward slash and then the title of PIZZA PLANET. Just after our surrounding div with our logo, we can then add our links to different areas or different components of our application. Let's add these inside of a nav element. To begin, I'm going to hard code another list until we are at the front and routing later in the course using the view router. The unordered list, the first list item, which is also going to be a link, is going to link to a Home route of forward slash. The link name of home. Each link, I'm going to add a span element with the Tilda icon to separate each one. The next one I'm going to copy the span and also the list item. Paste this in. This is a link to our menu components, which is forward/menu. The next one is for the contact us page. The href is simply forward/contact. The last one is for the about this link. Let's add this in. This doesn't need the span. We're going to move this. The text of about us. The href is simply forward/about. The next thing we need for our header is to add the scripts. The only thing we need to add for now is the name of our components. The name is going to be the app header. The next thing I wanted to do after the template and script is to also add the Style section where we can add these styles for header. Also include these scoped keyword, which means the styles will only apply to this single components and not for the rest of the site. Let's begin by selecting our level 1 heading, which is for the site title. We can make the font size a little larger. I want to set mine to be 1.3 ms. When we created our template just above, surround an inside subtitle and also our logo. We have this div with the class of header logo. I'm going to use this class to add a linear gradient, which is going to make up some stripes as a background image. Let's grab this. Just under our H1. We can take this as a class setting the background image. The background image is going to be a linear gradients. To set up our stripes at an angle of 45 degrees separate it by comma, we also now need to add the stages which the colors are going to appear. I'm going to switch between two colors to create the stripe effects. On the first color, which I'm going to add is a x value of d85226 and then 25 percent. This basically means that the start of the gradient from zero up to 25 percent will consist of this color. We can then add our second color, which is going to be the value of f79e38. This color is going to apply from 25 percent to 50 percent. The second quarter of the gradient, for the third quarter, we're going to switch back to our original color. Let's add the same. This is going to be from 50 percent up to 75 percent. For the last quarter of the gradient, we're going to switch back to our lighter color. Let's add this in. This we're going to run it from 75 percent onwards. We can then finish off our gradient with the same color. This will run to the end of the gradients, which is 100 percent. We can then specify the size with the background size property, which I'm going to set to a value of 80 pixels. Then 80 pixels. The display type is going to be flex. So in this, the flex will allow us to add the flex direction to be column, which will allow our items to be stacked on top of each other. We get the site logo on top of the site title. We can also add the align items property, set these in the sensor. Then finally finish things off with some padding on the top of some pixels. Keep this away from the top of the browser. But we add any more styles. Let's add this to our app.vue. So we can see this inside of the browser. Remember, all of the files which we created are standalone single file components. Which means tell a view exactly where we want this to appear inside of our projects. The app.vue is our main components and we can use this as a wrapper for all of our components. To begin at the top of our scripts, we need to add an import where we import our header from the file path of dot slash components and that header. We need a components property which we already have from the content provided when we created this with the view CLI. So inside here we can add the app header, which is going to be equal to the header which we'd just imported. So when registering components inside a vue, we should not use a reserved element name such as header. So what we're doing here is setting the header component to be a alias of app header. We can therefore references up had a loop in our templates where we want this to appear on the screen. So we can move this and add inside of lowercase the app header with a opening and a closing elements. Alternatively, we can use a self-closing tag just like this. This will also work. I'm having error appearing here, and it's the file path from the header. Let's just fix this. This is supposed to be PNG. So save this. Now we can go over to the browser. We now see our logo appear in with the background linear gradients. We also have the site title and also our navigation links just here. Just to finish this video off, let's add some styling to the rest of these links and we can also make the logo a little smaller. So back to the header.vue. We can scroll down to our styles. Let's begin by targeting the header logo image. So it had a logo, we can grab the image element and then set the maximum width p-value of 25 vw, which is 25 percent of the view port width. Next I'm styling for all links at the bottom, we can grab the unordered list. Set the padding to be a value of 10 pixels on the top and bottom, zero on the left and right. We can also select the list items and also set the display to be inline-block. Save this. Also we are going to finally add a media query, which is going to make this image a little bit smaller when we reach 900 pixels and above. Let's add this just after our list item. At media, we'll target these screens which have a minimum width of 900 pixels. We can then target our header logo image, which you have just here. We can add this inside and drop this down to a value of 20 vw. So now on a smaller screen, this is a body of 25 percent. We can increase to 900 pixels. Then we see the image drops down to make it a little smaller. This is it. Now for our header, we will come back to these components later on when we add a front-end routing. But for now let's move on to our homepage. 5. Home page component: Now it's time to add the contents to the homepage component file. As we can see here from this final finished version, will be adding the Welcome section, which is this section just here. This will link to our Menu when the user clicks on the "Let's Order button." If we go back, just below this section we may also have three separate sections, which is the order, delivery info and the history section. These information blocks are actually separate components and this will allow us to reuse them later on. We can switch between them, when we set up the view router. So for now we're going to leave off these three components, and just concentrate on this section just here. Let's head over to the home.vue, which is component we've already setup. We can begin by create in our familiar template and then nested inside here, I'm going to add two divs. So the first div is going to be the wrapper. This is going to be the background wrapper, which is going to be the surrounding container, where we can add a image using CSS, nested inside here we're going to have a background overlay wrapper, which is going to be for the box in the center. So this first one. Let's add the class of background this is for the image. The second div, this is for the box with the class of background overlay. So inside of the background overlay, we're going to start with the level two heading, which is the text of Welcome to Pizza Planet. After this, we add our image, which is the roller image which we just have here. Let's add the image inside here, which is the source of../. This is the Assets folder into the images and the roller.png. We can also add the alt tags of roller and then followed by the level three heading, which is the text of, "Feeling hungry?" But now we're just going to add a simple button, this button will be hooked up later on when we add the vue router. So for now we'll just add a h button. We can add a class for styling of order- btn and the text "Let's order!" So this is all the content for our templates. Just before be move on, we can also add our script and inside the script all we are going to do is add a name for our components inside of the export defaults with the text of home. Save this file. Just as we did with the header, we can nest is inside of the app.vue file and register this Home component. Go to the app.vue, let's go down. We can also import home, from our components, which is./ Components and then home. We then need to register this by adding this to the components objects. We can add a component just like we did here, where we import it by a name such as header or another way to do this is to use the name which we use when importing, so just home and this is fine if there is no naming conflicts with HTML elements. Just like early on when we did with the header, this is a HTML element name, therefore we had to give this alias of app header. So now we've got this imported. We can go up to the top, just underneath the app header, we can add our home inside here. H, save this file. I'm going to check this is showing inside the browser, says I have a component now displayed on the homepage. We will go and add some styling in just a moment. For now though, I'm going to remove the white space which is at the top of the app.vue, so let's scroll down. We could remove the default styling which is provided where it says about projects. This now pushes the header back to the top and we can now go all to the Home.vue, we can setup our style tags. I'm going to remove the scope flag and then begin with our headings. We scroll up, we have a level two and also a level three heading. Let's begin with these and type in the h2 and also the h3 and add some margin of two percent. Just after this, we can then target the background, which is the main container. This is where we're going to add the background image, which is going to be, and we'll take a look at the final version, this picture, as we see here. Let's select the background. First of all, we want to set the image, which we can do with the background property, by setting the URL and then passing in a file path. The final path we want is./, this is the Assets folder Images, and then the image which you want is dough.jpg we can also center this. Then set the background size to cover. If we save this and go over to the browser, we now have the background image. I'm going to set the height to be, 30vh. Which is 30 percent of the vue port or the browser height. Set the display type to use the flexbox. We can align the text into the center. Then finally, we can also align our box into the center too and we're going to line this vertically using align items, this is a flexbox property and we want to set the value to be in the center. So now we can move on to the actual background overlay, which is the text and also the image and the button. Just below the background. This is the background overlay. Where we also want to make use of the display type of flex. We can set the flex direction to be column, to stock these vertically. We also need a background, so this is more visible over the background image. I'm going to use a value of f1e6da. So we you can still see the background image. I'm also going to add the positive value of 0.8, to make this slightly transparent. We can to see this just here. We can control the width. I'm going to use a value of 50 percent. Center this with margin zero auto. Some padding inside of five pixels. Let's keep the text away from the inner edge. Okay, so it's all norrow centered. We need to reduce the size of this roll image. So we're going to get in again inside of the background overlay, select the image and we can say that the maximum width to be a value of 15 percent. We just now need to push this back into the center. We can do this with the flexbox back up in the background overlay. I set in align items, to be in the center. There we go, and then finally we going to target the Order button and give this a different background color and also some padding. So right at the end of our style sheets. We gave this button the class of order when this call our btn, which is this class just here. So let's grab this, add this in. Let's first start with the background color, which is going to be f79f38, a border-radius and we want to keep this small, so a value of three pixels is fine, some margin on the bottom of 10 pixels. Some padding to make the ball in a little bit larger of 10 pixels. We can then select the cursor to be a pointer. So save this and head over to the projects. We now have the background color, the border-radius and our cursor is now changing to a pointer. So this is now our basic homepage setup and displayed in the browser. In the next section, we will focus on getting our menu and our shopping basket all setup to receive data from Firebase. 6. Creating the menu component: When we created our header components, we added a link to the menu. This menu component which we are going to now start working on, will eventually be where we pull in all the menu items from our database. If we take a look at the final version and head to the menu, these items will be listed on the left-hand side, which the user can select which pieces they want to order. They will then be added to the basket of on the right-hand side, that can also increase or decrease the quantity and then finally place the order. This order will also be pushed to Firebase and also be available from our admin. Both the menu items and also the orders will be kept in sync with a central store two inside of our application, which we will take a look at later on. Now let's add the menu.vue components inside of our components folder. Let's go into the sauce, inside of the components. The menu.vue. The first part is to create our template, which will just be a HTML table to display our data. This table will be used to display our pizzas with the names and options available. This will just be static information for now until we get working with Firebase later. To begin, we add our templates, then inside we can add a div, which is going to have the class of menu on the sky wrapper. Inside of this div, this is going to have our menu and also the baskets. For now I'm going to have a comment of the menu so we can clearly see which section this is. We can then add a div with a class of menu. Inside of here we're going to have a level three heading, which will be the text of authentic handmade pizza, we’ll then set up our table, which will have some sample data in for now. Level three heading, I'm going to surround this inside of the tilde's, so authentic handmade pizza. Then we can set up our table just below. We are not going to have a table header, so I'm just going to jump straight to the table body. Inside of the table body, we’re going to set up free table rows. The first one is going to be for the pizza title, a second row for the description, and then a third row which is going to be for the options. Inside of the first table row, we can add our table data. Then inside of the table data, I'm going to add these strong tags to make this bold, and then a pizza name inside of the tilde. I'm going to add pepperoni, followed by a tilde at the end too. This is our first row. The second one is going to be for the the description. Add a new row just below the table data and then this is going to be the small tags to make this a little bit smaller, I'm going to add some Lorem Ipsum. If you're using Visual Studio Code, you can type in the word Lorem and then hit Tab, or you can add in any sample data you want, it really doesn't matter since this will be pulled from Firebase very soon. After this table row, let's create one more, which is going to be for our options. Our table data that starts with a nine inch pizza. Just below, we can also add the price. I'm going to add 695 followed by a button, so td, and then inside here we can add our button, which will be the plus symbol to add this to our baskets. The button needs a type of button and also a class for the CSS, which we once called btn underscore green, a right plus symbol. At the moment we have no way of telling view that we want these components to display when we click on the forward slash menu routes. Since we don't have a router setup just yet, as a temporary measure, we can add it into the app.view file, so we can see it's inside of the browser. Let's begin by importing this, just below the home components. We want our menu, our menu from here. We can also register this just under the home, and then add this above inside of our template. Let's check this out. Over inside of the browser, so there we go so we have our title, we have our pizza title, our description and also the option just below. This option will be a loop, so later on when we use the database, we’ll look through the available options and show the different sizes and prices. I'll just correct the spelling mistake inside of the menu. There we go. With this now in place, we can now add some style into our menu components. Slight head over to the menu.vue. We can then scroll down to the bottom. We can set up our style tags. I'm going to leave this as scoped for this component, so this only applies to this single file rather on the rest of the project. Let's begin with our level three heading, which is the authentic handmade pizza title. All we need to do here is to set the text-align, its being in the center. Next open gone to target, the menu wrapper. Remember the menu wrapper is going to be the main container. It would go up to the top. This is going to surround our menu and also the baskets. If we take a look at the final version, this is going to mean if we scroll this down, that the menu and also the basket will be stacked vertically on a smaller screen, then we'll add a media query, so these appear side-by-side. Let's go down and begin this now. To do this, we can change the display type to be flexbox, and then on the smaller screen we can set the flex direction to be column. We'll add a media query changes back to row very soon. Lets also target the menu, which is the left-hand side. I'm going to set the background color to be a value of F1, E6, DA, a border radius, which is going to be three pixels. We can also make this the full height of the browser by sending it to be a 100 vh. At the moment, it looks pretty small because we want to get one item, but we can make this see full height to the browser even without the content. This has to be height property to be 100 vh, some margin of ten pixels, add some spacing, and also some padding of ten pixels, the inside of the menu. Save this, scroll down and there's our menu. Now we just need to add a media query to make this a row on the larger greens. Still within the style tags, we can add the media query, which is going to target the screens which are a minimum width of 900 pixels. Then all we want to do here is to grab the menu wrapper, which we have here. Then I change the flux direction to below and also add some space in between, so the flex direction changes to row. We can then also justify the contents to be space between. This also means that later on when we also have our baskets, we’ll also have some space in between the menu and the basket sections. On this larger screen, we also need to set the menu to be a certain width so it doesn't span the full width of the browser. We can do this by targeting the menu class and then set the width to be a value of 65 Vw. I've got back over to our projects. We now see that we have some space over on the right-hand side for all baskets. If we shrink this down, this will now be the full width of the browser. Then this and also the basket later on will be stacked vertically. Okay, so this table looks now how we want it to, but we do need to set things up to loop through a menu with multiple items. We’ll do this in the next video where we will add an object to display more items into our table. 7. Looping through menu items: All of our pizza information will eventually be stored inside of a real database. But for now I'm going to add some menu items into our data property to work with. I'm going to do this inside of the menu dot view component. We need to add a script tag just bellow our template. We can then add our familiar export default where we can add our data property to store all pizzas. Inside of the return statement, I'm going to create an object to store these in called get menu items. For now we'll just set this up as an empty object. Provided with this course is a text file called pizza object which will contain all the data which we need. Have this available on the desktop. I'm going to open this up. Then we can grab all of the contents and paste them inside of our data. Let's select all, copy these. Then paste this inside of get menu items. All we have here is various objects. The first one is an object which contains a margarita. We have a description and then inside here we have a Options array. We have our two sizes. We have a nine inch and also a 12 inch pizza with the corresponding price. Then have a second item, which is a pepperoni, also with the description and the two options. With this data property now available, we can make use of views v for directive. To look through our data we can do this up inside of the table where we added all of the static data in the last video. To begin on the surrounding table elements, I'm going to make use of the v for directive to look through. We can add v for. We then say item in get menu items. Get menu items is the object which is added to our data property. We then store each individual pizza inside of this item variable so we can access is inside of our table. We're going to begin by removing the hard-coded value of pepperoni inside of the double curly braces. We can then access the item dot name. With all this inside of the small times we can remove the Lorem Ipsum. We can actually double curly braces unless I want to access the item dot description. Save this over to the browser and we can see if this is working. We see we have a small problem. When using Vue.js and also this is the same when using React to if you've used up before. We need to add a key to each item. We see the view is expecting the v bind directive with a unique key. To fix is when using a loop. We can also see we've got the red underline in the text editor. We can also bind a dynamic key property with the colon and then key. For each individual item, we need to add this unique key. This is all view come better, keep track of each item when we are adding, removing or updating a list elements. At the moment, our pizza object contains unique pizza names. We can just use up. We can say item.name. We can instantly see upon saving that's our menu items and now added. However, a better value for a key would be a Unique ID. When using our database later a Unique ID will be generated for each item in the database. We can come back and change this key later on. But now our free items which you have inside of our data. The next thing to do is to create a second loop, which is going to loop through all the options. At moment we just have the hard-coded value of the nine inch pizza. If we go down to our data property, we have two options. We have the two values of nine and 12 inch meaning we can add a second loop to go through these. If we locate the table row with the sizing inside of the opening elements, we can add a second loop would be four. Inside here we're going to loop through our individual options. Remember we have our individual pizzas stored inside this item variable. We can access item. Options, and then we can store each individual option in a variable called Option. We can then set up our dynamic data. Instead of the hard-coded values, we can ask the double curly braces. This can be option.size with the double quotation just afterwards to signal this is in inches. We can then remove the price, set the double curly braces to be option.price. Once we save this, we again see that we have a problem with the v bind directive. We also need to add this to our second loop two. Let's add a key. We also need to add a unique value to these two. We only have two items inside of our options array. Therefore, we can use the arrays index number as a unique key. We can grab this by adding a second value 12 before loop. Instead of just adding the option variable, we can add to the brackets and then add a second value which is for our index number. Since this is an array, this will be option zero. Then option one and so on. When passing the key as option with the index number. Save this and now inside the browser we see our nine and 12 inch options. Well done if you can see the three items on the screen. If not, don't worry just go back through. Check the code and try again until they get to the stage. Join me in the next video where we will continue with the menu components and push the selected pizzas to the shopping baskets. 8. Pushing orders to an array: In the last video, we successfully added the menu items to this menu routes. You can see from the final version, if you head over to there and then go over to our menu components, that we still need to add the basket on the right-hand side of the page. When the user clicks on a "Pizza," click on the "Plus Symbol," the item will appear on the right-hand side in the basket. Also the basket house burns to change the quantity and the total price is also updated. In this video, we will take the first step towards creating this by adding the baskets array to store the pizzas which the user adds to the baskets. If you're not already there, select the menu components from Visual Studio Code. The first thing I'm going to do is to add a data property called basket, which will be an array. Down to our scripts, inside of our data. Let's add just above get menu items. We can initialize our basket as an empty array, then add a comma just afterwards. This array will be used to store the pizzas, which is selected by the user. The other pieces to this array, we need to add a method to the add to Basket button. Let's scroll up to our button. Inside the buttons opening tag, I'm going to add a on click "Event Handler" with a click and set this equal to a new method which you haven't created yet called addToBasket. AddToBasket is going to take in two things. The first is the item, and then the second is the option. The item is the individual item from our loop, such as a Margherita. The option is the option of which pizza size has been selected, so that the nine or 12 inch version. Scrolling down, we can now add the addToBasket method. Just after our data property, that's okay, it's the closing curly brace and a comma. How we can set up our methods object just like this. I'm going to set this up as async, so we can make use of a JavaScript async/await method name was addToBasket, which takes in the item on the option which is passed when she calls. What do you want this method to be able to do? Well, won't say pizza is added to our basket. We want to push a new item to our basket array. We can use the JavaScript array method called push to do this. So let's say the soap, we can select our baskets. With this.baskets, we can use the JavaScript push method. The item we want to push is a new pizza object. We can set this up. We can grab the name from our item, which is being passed. This is the full pizza objects. So we can drop the item and then select the individual name. We can also do the same for the price. We can grab an item, select the price of the pizza. Also the size. The size is available inside of the options. We grab the option that size. Finally, we also want to set the quantity to be an initial value of one. Now with this in place, we can give this a test. If we scroll up to our templates, we can try to output the value of the basket and check that this is updated with each new pizza. Can have this anywhere inside of our template that you simply outputs the value of the baskets. Head over to our projects and into the menu. Let's try clicking on one of these. This is the 12 inch Margherita. You have the name and also the size inside of here. Let's try a nine in ham and pineapple. This has been added to our basket to. If we go ahead though and add the same pizza, once more. Whenever nine inch pineapple, we can see the inside of our array, we now have three individual items rather than the quantity being increased. We can improve this even further by first checking if an item is already inside of the baskets. If not, we'll add the new pizza. If it's already in the basket, will increase the quantity by one. Let's go back over to our method inside of here. Before we push our pizza to the array, let's first check the contents of the array. We can create a constant called pizzaExists. Inside here, we're going to await this.baskets and then make use of the JavaScript find method. Find is nothing specific to view js. It's actually a JavaScript array method, which returns a value of the first item which matches the condition we are about to provide. The conditioning is to check if the pizza name and the size has already been added to the baskets. Inside here, we said that by function, we want to add an inline arrow function. Here we're searching through our array and each item that is found is stored inside this piece variable with unwanted check. If the pizza.name is equal to item.name. This is the pizza remember which had been passed to our method. We also want to track two if the pizza.size is equal to our option.size too. If the pizza size and also the pizza name, it's both found inside of our basket. This means that this is going to be true. We can set up an if statement. We can say if pizza exists, then we want to increase the quantity by one. We can do this with pizzaExists.quantity++. What I want to return out of our function since we don't need to do the push method just below. Save this file, and now let's head over to the browser. We can try at the end a 12 inch pepperoni, a nine inch. Limits are a second 12 inch, and the quantity has been increased to 2, 3, and 4. Let's try it for one more. Let's say ham and pineapple. The quantity is now being increased with each item which has been added with this now in place our baskets is now working correctly. It doesn't look great at a moment. But our data is there in place for the next video. 9. Adding the shopping basket: We made a big step towards our functioning shopping basket in the last video by pushing our added items to an array. Now we can create a table to display the old items by looping through this array. Let's head back over to the menu dot view components. Well, I'm going to add this basket at the end, just above our closing div for the menu. Scroll over to the templates, and remember we created our menu section with the menu class. Let's locate the end of our menu. In place of our basket just here, make sure we still have the closing div at the end for our main wrapper. Let's begin by adding a comment. This one is for our shopping basket, our shopping basket needs a div, and I'm going to give this a class of basket. We can use this in the CSS very soon, we'll now add a level free heading at the top. I want to add a tilde to either side, with the text all baskets. Let's begin to construct our table for all of our basket data. The table is going to have the table body and then our first table row. The table row needs some table data with the TD elements and this first piece of data is going to be for the increase and decrease buttons. If you look at the finished version, this is going to be the plus and minus buttons and also the quantity in the center, we'll then add a second piece of table data, which is for our pizza, including size and then finally the price at the end. The first element is going to include our button. This is going to have the h small entity, which is going to be an ampersand, the hash, then the value of 8,722 with a semicolon. This will give us our negative symbol to deduct it from the quantity. You can also add a class, this is going to be the value of btn underscore green. But our CSS, I'm going to duplicate this. This is for the plus button, which is a h small entity of the ampersand, the hash and then the value of 43. In between here we also want to add a span element, which is for the quantity. I'm going to add this all this in as a value of 2. Underneath our td, we can add our second set of data, which is for the pizza name and also the size followed by alpha piece of data for this row, which is for the price, and any price is fine. We will come back and make this dynamic very soon. You can say this and see how this is looking over in the projects. We have our buttons, our quantity, and also the pizza information, along with the price, definition of our templates. Over to the final version, we also need to add this order total just below our table. I just want to hear we can add a p elements with the tags of all the total and a colon and then we can add a button to find the place of order. This button can also have a class to match the rest with the class name of btn green, save and refresh. Just to finish this video off, I'm also going to add some CSS to this basket, so much as the menu on the left-hand side. Let's scroll down into our style tags, down at the very bottom. We are going to share some common styling with the menu. We can also add the baskets. This is a class. This will give us the same background-color and border radius that we see here and also to make it the full width of the available space. Let's scroll down to our media query. The menu has taken up 65 percent. We can add to the basket width, let's take up the rest of the content, which is 35vw, and there we go. This is how our shopping baskets are now being displayed with some static data. Let's now move on to the next video where we'll loop through our basket data and display inside of this table. 10. Making the shopping basket dynamic: We now have a shopping basket table on the menu screen showing some static data. To make our data dynamic we can loop through the contents of the baskets array, just like we did with the menu on the left-hand side. We already know the basket array has all the information we need. Let's add this for loop to our table, I'll go to the menu components. Let's scroll up to our baskets table, and locate the opening int table tag. Inside here we have our table body where we can add our v for a loop. The item we want to loop through is the basket. We want to store each individual basket item in the item variable and we can also add as a second value our index position, which we can use as a key. We combined our dynamic key and set this to our index. The next thing to do is to go down to our static data. The first piece is the item quantity so, inside the double curly braces, we can access our item and grab the quantity from our object. Scrolling down the next piece is the pizza inside here and also the size. First of all, let's grab the item.name and then as a second value inside of a second set of curly braces, you can also add the item.size. Below this, we also have the price so let's change the 695 to be the item.price and its response to be item, say this and now obviously browser let's add some items on the right-hand side. I'll see the quantity has been increased with each Jupiter item a new item is added onto a new line now we're just missing the price of the end. Let's take a look we've got the item.price. Let's just check our method down at the bottom. This is just from the option so let's change this and now back over. We can try and add this once more, and we see the price. However, if we up the quantity of any one of these items, we see the quantity is increased but the total price is not. This is something we can easily fix we'll output the price. Let's scroll back up, we can multiply the price by the item.quantity. This will give us a total price, so we see this has been updated. We can add one more and the price is updated with each click. Good so now if we give the browser a refresh, we want to hide the text and also the order button when no pizzas has been added. We can hide our baskets using conditional rendering and only display if the basket array has a length greater than zero. Back over to our basket, which is the surrounding div just here, I'm going to surround this table with a second div where we can show and hide its contents. Add a div inside here and then we can add av if directive to check if our basket.length is greater than zero. This div will only show if any item has been added to our array. We can cut out the closing tag and then scroll down to the end of our table. At the closing div, just after our place order button. Just below, we can add a else condition inside of a separate div. We can say v else so the contents inside here will be a message inside of the p elements. I'm going to make this message dynamic and set this to a variable called basket text. Inside the sub just below in the date property set up our basket text where we can display a message to the user of your basket is empty. Save this, reload and there's our text of your basket is empty, using conditional rendering and now if we add an item to our array, this is now being removed and we see the items inside of our basket. You may be wondering, why do we set up our message is one here as a date property, instead of simply adding the text inside of our p elements. Well, this is because later on after placing our order we will also obtain this message to be a funky message. It will become more useful later on, next up we will add small methods to our shopping basket. We will wire up our increase and decrease buttons inside here, along with removing items from the basket too 11. Shopping basket methods: We now have a shopping basket displaying the pizzas which the user selects. There is some extra functionality and I want to add it to improve this. First we can get the plus and minus buttons working, so we can change the quantity of each item. Also related to this, when the quantity is reduced to zero, we want this item to be removed from the basket. Let's begin by setting up the methods to change the quantity back over in the menu of the components. We need to begin by adding some click handlers to these two buttons. Let's scroll up and take a look for our two buttons, which is this section just here. The first thing we need to do is to add a click handler for the minus button. So we can add @click and set this equal to a method called decrease quantity. When decreasing this quantity, we also need to know which item we're reducing so we can pass in the item. The plus button just below. This is going to work in a similar way. This takes a click handler where we are going to increase the quantity. Also passing in the item we want to increase. Now let's scroll down to our script where we can create our methods. So let's take a look for these. Just below our data, locate the end of our add to basket method, which is her. The first one I'm going to add increaseQuantity, which we'll receive the item past to it. Increasing the item is pretty straightforward. All we want to do is to select the item.quantity and increase the value by one with plus, plus. I'm going to copy this at a comma where you can setup decrease quantity. All we need to do for this is to change to negative, and then we're good to go. Save and then over to the browser. Let's add some items inside a here. So first of all, we have one pepperoni. We can increase this and the quantity is increased along with the price. Let's try deducting this and then taking this zero. If we keep going, we get a negative value. Of course, this is not something which we want. So we can fix this by creating a method to remove the item when the quantity is zero. So head over to our methods. I'm going to create a new method inside here called removeFromBasket. This is also going to take in the item which you want to remove. We can use the JavaScript splice method to remove the item from our array. We can select this.basket, which is our array. We can call the JavaScript splice method. Inside of the parentheses, we can add two parameters. The first is the index position of the item we want to remove. So we can grab this with this.baskets.indexOf where we are going to pass in our item. So this will find the index position of our item in the array. The second parameter is the number of items we want to remove. We only want to remove one. For these methods work. First, we need to call it when the item quantity is zero. Under this can be added in need decrease quantity method. Let's go down. We can set to buy if statement to check if the item.quantity is equal to zero. If it is, we want to call our remove from basket method, which takes in the individual item. Give this to save over to the browser and we can add some items. Start by removing the pepperoni, the ham and pineapple. This is all now working fine. We still have the place all the button to why group two, which is down at the bottom. But we can look at this later when we begin to work with Firebase and data stores. 12. Structuring the admin section: Welcome back, the Admin component is going to be a large part of this application with quite a bit of functionality to work through. To begin, we protect the page with the login form, as we can see here on the final version. Only authorized users can see the admin section. If we sign in, the rest of the admin, then becomes visible. At the top we have the current logged in user and also a logo bottom, followed by a new pizza section, and also its own components to allow the logged in user to add new pizzas to the menu, and below we can see all items which are currently on the menu, and again, we can remove items from our menu and also a database to. Down at the bottom we have a list of current orders, and these can also be deleted when completed. We begin again my creating its own component called the Admin W, and then we can add some basic structure. Over to our side bar into the components, the unmanned w. Inside here, we can add our templates where we're going to add a div as a wrapper with the class of admin. On this call wrapper. This will be the main wrapper for our admin. This is going to have inside Free different divs. The first one is going to be for the current user, this is going to be its own components. We're going to have the menu wrapper, and then down at the bottom, the orders wrapper. Let's add these divs in now. The first one is going to be a div with the class of current user wrapper. After this will create a new div, which is also going to have the class of menu wrapper, and the last one is going to be the orders wrapper, which will sit down at the bottom. We need to add our script just below this, we give our components a name. The export default. We'll add the component name, and we are going to call mine, the admin. Save this file, and we can see this inside of the browser. We can add this over in the app w. First of all, we can import this. I'm going to call this admin, and this is from the file path of dot slash Components, and then the admin. We also need to register this components down in the view instance. This is available to use inside of the templates. Go up to the templates. We don't need this menu inside here anymore. I'm going to change this to be admin. Back over to the admin, templates. Right at the very top we have this current user wrapper, which I'm going to come back to later when we have users registered. For now we can move down to the menu wrapper just below and create our table. That gives us a level three heading with the title of Menu. Below this, we can construct our table. Let's add the table head at the very top with the first table row. This table row is going to have two headings. If we go to the final version, these two headings are going to be for the item and also the text off remove from item. We can add these in, inside of the TH tags, the item, and then just below this, we can also add remove from menu. Below the table head. We can then add the table body out in a row, and this is going to be for our Pizza name and also the potential to remove. The first cell inside of the table data is going to be for the pizza name. I'm going to add Margarita inside here. This will be read from a database later on. But for now we can just study hard coded value followed by a button. This button is going to be to remove the menu item from the database. Someone give this type of button a class of btn_reds, and then for the cross, we use the HTML code, which is the ampersand times, and then the semicolon. Save this file and then over to the browser, we have a menu components but not used over in the App. Select just comment this out. While view instance. We can also comment out the impulse. Now, I'm see a very basic table with our menu items down at the bottom. The table is now in place, and we will come back to this later on to loop through all of our menu items, just like we have done inside of the menu components. I will see you now in the next video where we'll stick with our admin components and begin to work with the current orders. 13. Listing current orders: We can look at the final version of in the admin components. In the last video. We created the table from its menu section, and added in a sample item. In this video, we're going to move down to the next div, which is for the current orders. This is also going to be a table two where we are going to have a title at the top. We're going to have a table heading with the item, size, quantity, and price, and I'm going to construct our orders just below and also with the button to remove each item. We are now creating lots of components, and things such as tables. With static data is not the most exciting thing to do, but stick with it, it is good practice and we'll get to the database section very soon. So back over to the admin components, which is the admin.view. Now I want to move down to this orders wrapper, let's just change this, and then inside here we can construct our level three heading, with the title of currents orders. Then inside the brackets, we are going to hard-code in a value. So we'll save 5 orders. Then just below this, we can create our table. The table will start with the table heads, which will be the headings of item, size, quantity, and price. We'll add these into their own row, and then each one will go inside of a table heading elements. The first one is for an item. Let's duplicate this three more times. The next one is for the size, the third one for the quantity, and the last one is going to be for the price. Scrolling down below our header section, we're going to add the table body, with the tbody elements. Nest inside our first row, and this first row is going to be for our other number. I'm going to add a class of order and it's called number. It's order number section, taking a look at the final site is going to be this row which we see here. You will have a order number and also a button to remove this from the database. Most are going to make this into one cell two, by making this span all four columns. So inside here we can add a table heading. We can make the span all for ourselves, with cross span to be equal to four. Our order number, I'm going to add in the strong tags. So order number. I'm going to set any value inside here followed by our button which will take in the type of button, and also a class for our CSS, make this red. We have the class of button of btn_red. As the value, we can add a HTML entity of ampersands, times, and then a semicolon. Save this and now we want to see our projects and scroll down. We have our; table heading, the order number, and also the button. The next thing to do is to add a new row, which is going to display the pizza name such as; vegetarian, the size, the quantity, and also the price. A new row inside here. The first piece of table data is for the name. I'm going to add margarita. The second one is for the pizza size. The third one is for the quantity, these ones are too inside there. The fourth one is going to be for the price. Save and let's check this out. Good. We now have our table contents there, and we can now add a little styling inside of the CSS section, inside of the admin to view components. Scroll down below scripts. You can have the style elements. This can also be scoped to this components, where we're going to start by targeting the admin_wrapper, which is the main wrapper. All I'm going to do is add some margin of 10 pixels nested inside. I'm going to target our free sections; so the first one was current_user_wrapper, the second one was the orders_wrapper, and the third one is for the menu_wrapper. We can target all of these three sections together to keep the styling consistent. Some margin to giving some space in outside of the div, 10 pixels on the top and bottom and zero on the left and right. Some padding inside of the divs of 10 pixels. A border surrounding each one with a solid line of one pixel, and the color to be f79e38. Next down to our table elements, we can set the text-align to be on the left. We can make the width. I want to set this to be 70vw, to be 70 percent of the viewpoint width. Next up, we can target the order number action, and the table heading, to give this a background color, which is going to be light gray. This is value of ddd. Finally, once again the order number, but this time we're going to target the button. So the order number button, which is the one to remove the item from the database. I'm just going to add some margin of zero on the top and bottom. Add 10 pixels on the left and right. Give this a save and over to the browser. Reload. This is the current order section completed for now. If yours looks like this, congratulations. You are ready to now move on to add a new menu items, and we'll add this in the next video. 14. Add new pizza component: Over in the menu only finished version, these aren't new pizza section, is basically form to add a new item to the database. I'm going to create a section in its own components, called NewPizza.vue. You could argue that this could go in the admin file 2, which would also be fine. However, it is quite a bit of HTML code. So the admin component make it a little bit bloated. As usual, let's go to the components folder, and we can create our new components, inside here. So this is going to be NewPizza.vue extension. Inside here, we can add our [inaudible] template and we can have some basic structure to our form. So the form that's have the opening and closing tags inside the level free heading. 15. Form input bindings: With the new pizza form already, we need a way to add the users data and store it to our view incidence. We can easily do this by using V-model, which creates two-way data binding, and this means that the values of the form inputs will billing to the data property until bulky kept in sync. Let's begin by creating a new pizza objects inside of the data section. To our new pizza menu file, I wouldn't go up to our script section, where we're going to add the data property just after the component's name. We can return our objects where we're going to add our new pizza objects. This new pizza object will form a structure of how our pizza will be saved to the database. This object will follow the same structure as what we use in the menu W components. Let's go over to our menu.view. We can go down to get menu items inside of our scripts. I'm going to copy all of the contents of one of these objects, so we don't need the surrounding curly braces. Let's grab the array closing tag all the way up to our pizza name. We can copy this and then at this inside of our new pizza objects. The idea here is to use this as a template. I'm going to add EG at the start of the name and also EG at the start of the description. The reason for this is because of two-way data binding. We mentioned two-way data binding before and how this data will be linked to our form inputs. My link list is well formed, it's actually, we'll see inside of these form inputs will be EG margarita and also EG followed by a description which will prompt the user what's typing. Then, since this is two way, when the user types in anything into these inputs, it will then replace the values inside of this object. We can then go ahead and push this new pizza at the database. Let's first set this up using V-model. We can use this form input fields loop inside our form. Let's go up. We'll start with the name. We can add V model. Then we combine this to our new pizza objects. Then the field name of name, I'm going to copy this section and then go down to the description. Inside of the text area, let's paste this in, and assuming new pizza.description. Here I'm also going to set the initial rose to be a value of five. When X have the option one section and into the size. If we go into the inputs, we can paste this in. But this time we want to access the new pizza. We want to access the options, which is an array. The first array value is 0, and we can access the size. Next up slope in option 1, we have the price. So many pizza, the options still at the index number of zero and this time we want to access the price. For option 2, we begin with the size. This is options, but this is the first item in the array. Just confirm if we go down inside of our array, the first item is position 0 and the second item is position 1. Position1.size. Then for the price, options born and then price. Service, new pizza components and we can check the silence over in the browser. He will see the text of EG margarita, the description and also the size and prices appearing in the form fields to. This all seems okay. To check the binding is working correctly, we can add a click listener to the button down at the bottom, which is going to trigger a method. Down to our bottom, we can add a click listener without click and set up a method which I'm going to call out down to all view instance. After the data property, here we can set up all methods. The method name was odd. Inside here for now we can run an alert, just with the message of method triggered and so we can see the results of our object being updated in real time. If we go inside of all form, we can also output our new pizza inside of the double curly braces with this dot new pizza. Over to the browser. We can now see our initial pizza object down at the bottom. We can then make any changes inside here, and we see them reflected immediately inside of our data. We can also obtain the description. We can obtain the size. Let's try updating both these on the corresponding size and price also changes too. Good, what is now all in place? Let's now move on to the next section where we'll start to work with our Firebase database. 16. Setting up our Firebase database: With the NewPizza data now being successfully captured, we now need to set up our database to store this information. I'm going to be using Firebase for the project's backend, and in particular the latest Firestall database. We will also soon make use of a package called Vivax fire, to keep our project data in sync with this database too. Also later on in the course, we can also use the Firebase authentication facility, to make sure only login admin users can access certain data. Let's begin head over to firebase.google.com. If you don't have an account, you will need to sign up and then head over to the console. Inside of the console, we can now create a new project. I'm going to add a new project here, and call mine Pizza Planet. Click on "Continue". I'm not currently going to enable Google Analytics, so I'm going to create a new project, and just give this a few moments to go ahead and create. Once it's done, click on "Continue" and you should be taken to a page which looks similar to this. We're going to be using the Cloud Firestore as our backend. You can either click on this section here to create the database, or click on the option in the menu. This is going to get us started with a new database to our Pizza Planet project. Click on "Create". Before we create this, we have two options. We have the production mode, where the data is more secure, but we can start in the test mode, which will allow our database to be kept open for reading and writing data. We'll come back to this later and change our security rules. Then click on "Next" inside the test mode. We can complete this and finalize our datastore. Once this is done, we then taking it to our database home section, and very soon this is where all of our data in our database will appear. We can also manually add a collection too if we wanted. A collection is a group of data, which will be our orders and also our menu. I'm going to click on "Cancel" since we are going to be pushing data from our project rather than adding this in manually. To add this database to our project, we need to access our Firebase settings, which we grab from the sidebar, and then project overview. We're of course using Firebase on a web project, so click on the web icon just here. We can then register our app. I want to call mine Pizza Planet. We can register. This will give us access to our configuration settings, which needs to add to our project. I'm going to copy all of the concerns from the config option, so the API key, right down to the App ID. Let's grab this, go over to the project. Inside the terminal we're going to begin by closing this down and installing in Firebase as an NPM package. We can do this with NPM I, on the Firebase package name. While this is setting up, we can then create a new file in the root of our source. Let's go inside of the source, inside of the sidebar, create a new file. This can be called the firebase.js, and it's going to be inside of this file where we can add our configuration. Let's start by importing our Firebase package from firebase/app. As a second import, we're also going to be importing our firestore, which is available from firebase/firestore. If you've used Firebase in the past and just simply imported Firebase, the more modern versions of Firebase, do allow you to select various packages, such as the firestore, will also later on be importing the authentication. These all split up into separate modules. Let's make these file sizes smaller. We can then set up our constants, for our config option. This is going to be an object, where we can paste in these settings, which we just grabbed from Firebase. Just after this, we can grab our Firebase variable, and then use a method which is called initialize App. To initialize our App, we also need to pass in the configuration options. After this, we can also create a second constant, which is called DB, and this is going to be a shortcut to our firebase.firestore. With a need to create a database reference, I'm going to export this reference, so we can use it elsewhere. We can export a constant called, dbMenuRef. This is going to be a reference or a shortcut to all menu collection inside all database. The shortcut is going to be a linked to our database, and then pass in the collection name, which is going to be menu. This menu folder will be created for us when adding the first pizza, if it doesn't already exist. So we don't need to go to Firebase and manually add this inside the console. Now all we need to do inside of any components, is to import this dbMenuRef. Then we can call any of the Firebase methods we need, to save the menu item, remove, update, or delete. Save this file and let's go back over to the NewPizza.vue file. We need to import this reference inside of our scripts. I'm going to do this inside of the curly braces, since this is a named export. So dbMenuRef. We can import this from the file path of../, and our firebase file. At the moment, if we go over to our project, when we click on the "Add" button, we trigger an alert inside of the browser. But instead we can now use this menu reference and use a Firebase method called art to push our NewPizza to Firebase. Let's scroll down and replace our alerts, by accessing the dbMenuRef. Access the Firebase add method, where we are going to push this.newPizza. We need to restart our server, with NPM run serve. Over to the admin inside of our project, and change the name. I'm going to add a Pepperoni. We can also change the description, [inaudible] mozzarella and pepperoni. Let's also alter the prices, so seven, and let's make this 11. Click on the "Add" button, over to our database and heads over to the database link. We now see our menu collection has automatically being created for us. Inside here we have one document. This is the document's ID, and then all the information from our form. We have our two options as an array, with the updated name and description. Hopefully this has all worked for you too. If not, do go back and check the code, it is usually something as simple as a typing error. If you can see this in the database however, you are now good to move on to the next video. 17. Adding the login component: The admin section of the app needs to be in area, which only registered users can access. We don't want any visitor being able to add or remove pizzas from our menu or access any of the current orders. Therefore, we need to add use authentication to our app, and we can do this by using the existing Firebase projects. First, we need to add a login component, which we can place inside of the Admin, and we're going to do this with a new component called Login.view. Head over to the Components, create Login.view, where we can begin to construct our templates in the usual way. I'm going to add a wrapper. Let's add a div with the class of login_wrapper. Nested inside, we can have a form. This form is going to have two sections. We are going to be logging in using the e-mail and password combination, so we're going to create a wrapper div first of all, for the email. The e-mail needs a label, so this is for the e-mail, and then inside here we can have the text of e-mail address. Afterwards, we need our form inputs. The input type is going to be for e-mail, the id of e-mail too, and then the placeholder value, which is going to be enter e-mail. After this section, we can then add a second div still within the form. This one is going to be for our password. The label for password, the text of password, the input is going to have the type of password along with the id, and once more, the placeholder of password. To finish off this form, we just need to add a button just before the form closing tag, and this is going to be the type of button, the class of btn_green, and then the text of sign in. This component will now need to be imported and registered so we can use this over in the admin file. So I head over to the Admin.view, down to our script where we can import our login components, the file path. This is also in the components file so the file path is simply./Login. Then register our components, and then up to our templates where we can add this in. I'm going to add this near the bottom, so just above the closing div for our wrapper, let's add our login components. Save this file and then go to the Admin in the browser where we see our new form down at the bottom for the e-mail and password. The position of this component is not really important at this stage since later on in the course, when we have access to the user's logged in states, we will conditionally render these components, so this is the only thing which the user sees on the page. In the next video, we'll head back over to Firebase and get to work with our user authentication. 18. Enable Firebase authentication: In the last video, we added a user login form which we have down at the bottom of our admin. This will be used to pass data to Firebase and check if the user is allowed to access this admin screen. Firebase makes add-in authentication easy follows to head over to the Firebase console. We see the authentication option in the menu on the left-hand side. We can then select a sign up method where we can set up authentication using various providers. We can make use of social media such as Facebook or Twitter or we can use a email and password combination, which I'm going to click on and then enable. Once this is done hit Save. You will then see the enabled status just in the middle here. Click on a user and now we can add a user to Firebase. Click on ''Add User'' where we can add an email and also password. I'm going to add test them on and then Add User. Of course, a stronger password is required if using this in production. There is also a way to register users from within the app too and it shows this in the documentation if you would interested. There is various methods such as signing with email and password. But this is more suited to apps where public users can register rather than our use case, where we simply have a admin who can login it to the back end. Now we have a user registered, we need to set up our authentication in our Firebase config, so go back to our project and then the Firebase.js file. We can then import our off module from Firebase just like we did with the five-star just above. We can select Firebase forward slash auth then at the bottom we can create a reference to our Firebase authentication service. I'm going to export this as a constant, so it's available in other files. I'm going to call this constant by a base auth and set this equal to Firebase and access the auth method. Inside of the auth files, just like we did with the menu reference, we can access our authentication methods by using Firebase auth as basically a shortcut. We can then go to the login view components and now we can import this auth reference from the config file. I'll blow our templates. Let's create our scripts. This is a named export, so I'm going to import this using the curly braces, so the name was Firebase auth and this is from the file path, which is dot dot slash and then Firebase and we're going to make use of this authentication service to create the sign-in and sign-out functionality. Let's begin with sign-in by adding a click handler to our sign-in button adjustable. On just this line here we can create a click handler use dot prevent to prevent the default behavior of a browser refresh set this up to be equal to a method called sign-in and this method we can now create low inside of our script. First of all, inside of our export, we can add the name of our component which is login. We also need to setup our methods and the only one at the moment is sign-in. Inside here we can access all of the available authentication methods which we can access using Firebase auth and this is what we'll begin to look at in the next video. 19. Signing in and out: We enabled our authentication with e-mail and password in the last video. This means we need a way to capture the e-mail and password which the user enters, and we can easily do this using V-model. The first step, is to add e-mail and password as a data property. So we'll do this inside of our export, setup the data, and inside we'll return our data as an object without a comma used after the data. We can setup the email initially to be an empty string and also the same with the password. We can then use V-model to synchronize this with our form data. Let's first go log to our email. Inside of the form input, we can add V-model and set this equal to our data property which is going to be email. We'll do the same. Just below inside of the password input, V-model and this time the data property is going to be the password. We can then scroll down and to finish off the sign-in method, which we started in the last video. First of all, I'm going to mark this as a async function. We can use async await. We can also add try and catch. We can add error handling, passing in the error which we'll deal with in just a moment. Let's begin in the try section where we're going to sign in and store the returned users data. First of all, let's grab our reference to our firebase authentication. Therefore, you can access all of the available methods which we need. The method which we're going to use is a Firebase method called sign-in with email and password. Inside this method we simply pass in our email and password. We have this available on the view instance. We can all access this.email and this.password. We can also await on the data coming back. This is all we need to do for the try section, let's go down to the catch area to collect any errors. We're going to access the error object and store the data inside all so variables. The first one is going to be the error code which is available from error.code. The second constant is going to be for the error message, and the error message is available from error.message. After this we're going to display some alerts, which is going to be for the error messages. To begin, I'm going to check if the user has entered an incorrect password. We can do this by checking if the error code is going to be equal to a string which is auth/ wrong password. If it is we can create a custom error. So let's create an alert with the screen of wrong password. If the password is correct, we can then create an L-section which is going to catch all of the error messages, so let's add a second alert with the error message or with the browser, we can now give this a test. Scroll down to the bottom of the admin, and let's open up the console. We can begin by adding an incorrect password. Let's add [email protected], on the password as test, sign in. We'll get the error message telling us that no user has been found. Let's try the correct one, which we added inside a Firebase and an incorrect password, sign in. We get the message of wrong password which we setup. Let's try the correct password. So test them on. Now we've used the correct email and password, we don't see any errors. Later this login component will hide to reveal the admin so the user knows it was a success along with displaying the logged in user's email and also a sign up button. This sign up method is a little simpler and this will go inside of the admin component. Let's add over to the admin.view. Look at the top of our template we've already created a div for the user area, which is the current user wrapper. Inside it will look like this. If we open this up, create the span, which is going to be the text of logged in as, followed by colon. Below there's a button with the text of sign out. This also needs some attributes inside of the opening tag. This is a type of button, a class, BTN red. We can add a click handler where we are going to prevent the default behavior. The method which we're about to create is going to be to sign out. Now we need to access a new Firebase method/ scroll down to our script where we can import and we'll off module or impulse inside of the curly braces since this was a named export. We can import Firebase off and this file path this time is../ and then Firebase. After our components, we can then create our method. So setup our methods, and then inside here, we can create an async function called sign out. Setup a try and a catch section. Passing in the error. Signing up with Firebase is pretty straightforward. All we're going to do is await, Firebase off. The method which we need to access is sign out. That's all we need to do inside of the try section. We can then catch any errors by alerting a message to the user. I'm going to add this inside of the [inaudible] So you can insert a variable. Error, signing out followed by a comma, and insert our variable of error. Let's give this a try over in the browser. Let's reload and clear the console. Let's try all of our error messages. First of all, a wrong email and password. We get the message of the user may have been deleted. We can add the correct email and incorrect password, and we get the incorrect message. Let's try the correct password, sign in, we get no error messages. Scroll up to the top. Now we're logged in, click on sign out. We don't see any error messages. So that seems to be working fine. Later in the course, we will add some feedback to the user, show a new email address when logged in, but for now this all seems to be working fine. 20. Final components: We're making good progress with this application so far. Before we move on to the next section, which will be to look at routing, I just want to first add the remaining components needed for this project. They're going to be pretty simple components such as an About Us and Contact Us page. But they'll be handy in the next section where we'll see how we can use routing to switch between them. One of the final components which we need is the About Us components so let's open the sidebar and create a new file called About.view. This is going to be pretty simple where we create a templates but now I'm going to add an empty div. Also create our script section and the component name which is going to be about save this, and back into the components we can create our second file, which is going to be Contact.view for the Contact Us page. Create our template inside here, so this is going to have a div with the class of contact_ wrapper, a level for heading with the title of Contact. After this, we're going to add our address for the contact section. At the top we're going to add the name of Pizza Planet inside the strong tags. Then we can make up a fictional address separated by break tags, add these onto new lines. Let's simply make something up of address 1, Copy and Paste this in a few more times, and also a phone number and also make this up. There's always a second set of address tags and it's just going to be for our e-mail. Inside this strong tags let's add the title of e-mail, followed by a break tag and then a e-mail address inside the P elements. Now we can add any e-mail address inside here so contact at pizzaplanets.com. A script tag, just below this and only script tag needs is a name of the components, which is contact and then we can add our styles just below. I'm just going to add some basic styles for our contact wrapper, which were added as our surrounding div. This is a class, so the backgrounds I want to add a hex value of f1e6da, a height to the components of 100 percent of the viewport height, I'll apply by some margin and padding, so 10 pixels and also the same for our padding. The next component is going to be for the Delivery Info so this is Delivery.view. Starts off with the template as usual, a surrounding div, which is going to have the class of info_block. A title of Delivery Info and I'm going to add the tildes on either side. A second div after this with the class of info block content. Just so we can target this inside of the CSS. We can add some sample text inside of the P element so I'm going to type in lorem, hit Tab to get some sample data. After this, we can add in an image. For the image source, we can grab this from our images folder. This is inside of assets/images, and then the name of delivery.png, the alt texts of delivery image. Then all we need to do after days is add our script, which is going to have the name of our components, which is going to be delivery. The next two components of history and ordering guide are going to be pretty similar. I'm going to copy all the contents from this file, create a New file and this is going to be History.view, Paste in the contents. All we need to do here is to change the title of history, the image is planets.png, the alt text of planet image. Then the component name of history, save this and the very last one which we need to create is for the ordering guide, based in the same data, and we can make use of this. The text of how to order the image source instead of delivery is going to be order.png, the alt text of all the image and then finally the title of ordering guide. This is now it for our components and most of the project is now setup. We don't need to register any of these components because we will be displaying them using routing in the next section. 21. Router installation and setup: Welcome back to this brand new section. Here, we are going to take a dive into the Vue Router. The Vue Router will allow us to create routes, to navigate to different parts of our application. At the moment, without the router, we just add in a components we're working on into the app.js file. We can see on the screen, a router will allow us to switch between components for different URLs or pages. This app is built as a single page application. This is quite common for JavaScript projects. We use webpack to bundle all of our components and dependencies all together into one main bundle file. This means when we first visits our application, we'll request this bundle from the server. The server will usually return only the index page in all cases, and then JavaScript handles switching between the pages. All of our components inside of the browser without time to make another request to the server. Hence the name single-page applications. This results in our app working really fast as this JavaScript is a lot faster than a round-trip to the server to fetch a page when we need it. To get started with the Vue Router, we first need to install it. We can do this by using the CDN link, which is available on the router.vuejs.org site. If you head on to the installation, you can grab the CDN link from here, or we can install the module using npm, and this is what we are going to be doing now. Over in the projects in Visual Studio Code, head down to the terminal. I'm going to install this with npm i, and the package name of Vue Router. Once this has finished installing, we can go over to the main.js, and begin to set this up. The file is helping create and import. it's pulling our node module. So we need to import the Vue Router. and the package name was vue-router. Also, since we use modules or separate files which webpack bundles together, we can declare we want to use this router in all of our files by adding view.use. Inside the view.use we then passing our view router. This is available in all files, meaning we don't need to add the import statement at the top of each file. We then need to setup the new Vue Router instance, which will take in an object. Just below this, we can set up our constants called Router. This up to be a new instance of Vue Router. Personal objects. We will be adding to this object for all this section, starting in the next video, where we'll actually set up our routes. Then we can inject our router into the view instance just blow by adding in this constant name of router. Inside the new view instance, passing our router. With this now in place, our router is setup, and ready to add some routes to switch between components. This is what we'll get to in the next video. 22. Creating our routes: We have our router now installed. It's time to add some routes to allow us to switch between pages or components by calling the main.js file, which we added our route to instance to in the last video. We can either add our routes directly inside here, or to keep things nice and neat. I'm going to set up a new constant called routes and create a new array just above routers and array, which we can add an object, eat routes. Inside this object, we need to define a path. Let's start by creating our objects. We can pass in the path property. Then we add the path which you want to navigate to. The Home route is the forward slash. Or for example, if we add forward slash menu, this will be our URLs which are as pizzaplanet.com/menu. Let's get started with the home routes. Then we need to declare which components we want to render when the user visits the forward slash route. I'm going to navigate to the home components. We will also need to import this component in just a moment. The second routes I'm going to add is for the menu. Again, as I string forward slash menu, which is going to map to a component, with the name of my new. Then up at the top of this file as ever, we can import our modules, all our components. Import, the home component. This is from our components directory, which is./components/home. These other command is going to be our menu, the same file path components/menu. Now we have our two routes set up when X needs, pass them to our router incidence. Scroll down, it's while routes a constant, all we need to do is simply passing our routes from above and make sure this is routes to allow us to switch between these routes, we need to modify the header navigation links. Let's go over to the header W. We need to use a router link component, navigate between these routes. To begin, I'm going to comment out the existing link. Let's comment out the a link, the home menu, also contacts and also about us, any place we can add a router link. Router link just looks like any other HTML elements. A router hyphen link, this has an opening and also a closing tag. We need to close this off. Inside the opening tag, we can then add To property and then add a forward slash. These To properties we just added is the path which you want to link to and it is much is one of the routes we've just setup in the main.js, the corresponding components will be rendered. Inside of our router link, we can again passing our link using the a elements, the link name of home, and then close off our link being careful not to add the href property inside here, since we use the view router to handle all this. I'm going to copy our router link, scroll down to our Menu. You can then change the router link to be the forward slash menu path. The title of menu go down to Contractors. The path is forward slash contacts and then finally the same for about. Now the view router knows exactly which components we want to render for each route. But we also need to tell the view router exactly where we want them to be displayed in our projects over in the app.view file. The final step is to add the router view components. At the moment we've got the admin and the home displaying at the same time in place, we can add the router view. This has an opening and also a closing tag and this will be the location where the rendered component will display. This basically acts as an outlet for whichever component is selected from the menu. This means we can now remove all of the components from our script below, still need the app header so we can leave this one in or we could remove the Admin menu and home. We no longer need these. We can also clean up our components, leaving just the app header. With all of this now in place, we can start up our development server with npm run serve. Head over to the browser and we can open this up in our pot, which is localhost 8080. We have our home component. Let's click on this. We can then go to our menu link and we say this is rendered just below. Back to the home. Remember in the main.js, we only set up the Home on the menu routes. If we click on the contact and about us, we don't have any content just yet. It is now in place. Let's now move on to the next video, where we will take a look at the router link components in more detail. 23. Router link in more detail: In the last video, we successfully added the router link. The link between paths inside of our application. If we head over to the browser and then go to right-click and inspect, we can open up the developer tools and take a closer look at the output the code. If we look for our header section, open this up and then down into our nav link, we see we have our unordered list. Inside of our unordered list, we have our list items where we have our link rendered inside here. However, if we now open up the link, we see a second a element nested inside. We do know if we go to the header, the view file, that we should have a single a link because we added this in the last video. Why did we see two links instead? Well, this is because by default, the router link component renders a a tag. We can change this by adding a never prop called tag, which will allow us to setup the router link to be a different type of element. I'm going to go over into the header. Inside of our router link, just after the two prop, we can add a second probe called Tag and set this to be a list item. This also means we can now remove the surrounding li tags since we don't need these. Remove this and also the one below. We can also remove the comments. This is on our boutons. We can do the same just above. We can remove the last item, sets up a tag to be again a list item and do the same for the first two. The menu remove the list item, tag of li and finally the same for the home components. Give this a Save and back over to the developer tools. If we give this a Refresh, we can now go back into our header, into the navigation, the unordered list and open up one of our list items. Inside we see a single link is rendered and we still have the surrounding list item. Link is looking more like it should be. Also you will see there are some added classes to the surrounding list item. There's router link, exact active, router link active two. Router link exact means the path must be an exact match. As an example, when using the home route, we have the forward slash by itself. In another route, such as forward slash my new, this also begins with a forward slash two. Without this exact class, defaults lush would be much for all routes. In the exact class means the whole of the path must be an exact match rather than just looking at the forward slash at the beginning. The second class added is router link active. View router automatically adds this class to the current active link. We can see this in action when we click on the above links. If we go to Contact Us, we see this is now being removed. Router link active is now being placed on new contact link. We can also take advantage of this class to add some custom CSS. You may be also wondering why use router link at all. After all, we already had an a tag where we could just add a link too. Well, there are a few reasons why using router link is a better approach. In single-page applications, the idea is that you make a request to the server for each homepage. Each page after is then switched by the router inside of the browser so we don't need to keep making requests to the server. Using router link intercepts the click event so the browser will not try to reload each page. Instead, it just switches between the components. This is one of the reasons why we don't our the hatred attribute the a link because this will make a new request to the server. Also, soon we will be looking at different modes called History and harsh and we will go over these soon. Put router link also allows us to switch between these modes, without making any extra changes. This is just some extra details to make the router link render exactly how we wanted to. 24. Binding and dynamic routes: Sometimes when we create routes, we need to take into account that paths to certain pages can also change. For example, inside of our URL, we could go to the home routes and then have forward slash user and then forward slash some username. This username section will be of course different for each user. So we may want to use the same components for each logged in user or the menu we may have some different sections. We can have forward slash menu and then for example, we can have drinks, or we can have food. We may want to show the same menu components, but just skip down to different sections of our menu. However, this will be difficult because of the paths for the router, as we've already learned, needs to be an exact match. For this use case, we can use dynamic route match in, which involves telling the view router, which parts of the URL may change and we can do this in the routes over in the main dot js. Let's head over to this file and we can set up the dynamic segment by adding a colon followed by the name of our choice. So inside of the menu, we can add a forward slash and then use the colon to declare that this section will be a dynamic part of the URL. By adding this, the menu components will be displayed each time the URL ends with forward slash menu and then forward slash any name inside here. The dynamic segment can be any part of the URL too depending on the particular need. For example, we could have a dynamic section and then forward slash and then a hard-coded section. This is useful for things such as admin sections, where we may have a forward slash, a user ID and then for example, forward slash orders. Another thing to note too, that this name which we gave the dynamic section, also acts as a variable. We can access the data inside of our components by using this variable name. So if we go over to the menu components, menu dot view, and then scroll up to the top of our templates just above our menu section here. Inside of the double curly braces, we can use $ symbol route to access all of our route information. We want to access the parameters from dot params and then the variable name of items. Give this file a save and over to the browser inside of the URL. We can then access our link. So let's go for forward slash menu and then our dynamic section, which can be any word we choose, I'm going to add drinks hit Enter. We now see our menu components has been rendered and this is also pulled out the URL parameters and I'll put this to the screen. This is some functionality which we don't need in our application, so I'm going to remove this and restore the menu back to forward slash menu. But this is something really useful to know when using the view router. Also in the menu, you can change this to be forward slash menu. While you also want to subject off dynamics sections, the actual paths in the router link component can also be dynamic too. For example, if we go over to the header dot view inside of our router link, the two prompts which we did have a hard coded value of forward slash menu, contact and about. We can also make these dynamic too by adding them to our view instance. So under the name we can add a data property. We're going to return an object too. Inside here I'm going to add four data values. The first one is going to be the home link. Set this up as our forward slash string, the menu link two, which is forward slash menu, the contact link of forward slash contact and then finally the about link at the bottom of forward slash about. We can then use these data names up in the router link, prefixed with a colon to indicate that this is dynamic. Rather than this hard-coded string value, we can add to the colon just before and we can set this up to be home link. Same for the menu. This is going to be menu link. We can add the colon to this and we'll do the same and just below for our final two links, add the colon. This is contact link and the about section, this is the about link. Say this, and head over to the browser and let's go to the home. You see the forward slash at the end, the menu forward slash contact and finally about. This is maybe something which you will not need to use a lot. However, it is nice to know that this is available if we have a use case for it such as if we need to dynamically create a URL and insert any variables into it. We can then add these to our data property and then update the URL accordingly. So this is it now for dynamic routing. In the next video, we're going to take a look at exactly what this hash is inside of the URL by taking a look at the history in hash modes which the router provides. 25. History and hash modes: You may have already noticed that since we began to use the view router, there has been a hash added to the end of the URL. This is because by default, the router is set to hash mode and the reason this hash is added is to avoid a page reload when a route changes. I mentioned earlier that when using single-page applications, we only want to send the request to the server for the main index page only. Then the routes takes over from there and switches between components without sending server requests. This mode is useful for our single page applications, but generally, we don't want to have a hash inside the URL, as it would look much nicer without one. To remove the hash we can change the hash mode to history mode and we can do this over in the main.js file. Let's head over to there and we can add history mode to our router objects. Just underneath our router object where we added our routes, we can add the mode setting and change it to be a string called History. History mode takes advantage of the HTML5 history API, which allows us to change a particular URL without needing to refresh. We didn't need to add the hash mode before to our view router instance because this is default. Now if we save this file and go over to our application, click on the Home link. We now see the hash has been removed and the same if we click on our over links to. This now looks better, but also creates a small problem we need to work around. We also need to configure our server to handle this new setup. Our server needs to return the index or HTML in all cases, including any 404 errors. Once this has been returned, the router takes over and handles the switching between components on the front end. If you do this on a real production app, you will find some server configuration examples in the vue router documentation. If you go to the vue router documentation and inside our HTML5 history mode option. Here, if we scroll down, we could find some example server configurations where we can see these examples for different types of server and this is something which we'll come back to later on when dealing with hosting but for now, this is where you can find some examples of configurations if using a different server. The last thing to take care of now is the index.html page, which is always returned from the server so we don't get any 404 errors reported by the server when a URL is not found. If we go to our project and type in a unrecognized URL, we don't get any components showing up on the screen because we don't have any routes setup which match so we need a way to handle this case and we'll take a look at this in the next video. 26. Catch all routes and redirecting: We finished in the last video by mentioning that since we have changed our router mode, we need a way to handle any follow for errors when a URL is not found. This is a pretty simple fix. All we need to do is add a catch-all route to these cases and we can do this back in the main dot js-file. We can create a new route which is going to handle it up in our routes array. Just after the menu, we can add a new objects, where the path is going to be equal to a star. The star as a URL path will cover us for any paths which are not matched above. Just like our other routes, we can add a component to display if the path is not matched. For example, here we could add a component such as the follow four-page. Alternatively, we can also add a redirect, which is going to redirect to any page which we choose, such as the home route. If we say this and give us a go in the browser, we can add in a unrecognized URL. It's enter, and we redirected to the home route. These are some options to cover us for unrecognized URLs. We can either redirect to a different page or set up a custom components with some instructions to the user. This redirect can also be used on any other routes too, it's not reserved just for the catch-all route. Coming up in the next video, we'll keep on the subject of routing and look at how we can add nested routes to our application. 27. Nested routes: The routes we've been using so far have been pretty simple. We have all of our menu items. You stand here on the same level with no child items. The router makes it easy for us to add nested routes, to group together routes which quantity related. We setup components in the last section. Just the contact and ordering guide, which you can see inside here. This idea for us to group together as child or nested components of the about us link back inside of this main.js file. We can start this off just like any other route by adding our object to our route array, we can add a path. This time we're dealing with the about link, so this is forward slash about. Just after this, we also want to render out a component. The main components when clicked on is about. Then to add any nested child routes, all we need to do is separate it by a comma. We can add the children property and then set this up as an array. Inside here, we're going to add some options, pretty much just like we did with our top-level routes. We're going to set up an objects where we set up a path. The first path is for forward slash history. Just like above. We then render out a component. I'm going to give the component's a name of history, which will import in just a moment. Separated by a comma, I'm going to copy and duplicate this two more times. The second one is going to be for delivery and the component is also going to be delivery too. Right at the very end, we're going to replace this with the Ordering Guide and also the path which is ordering hyphen guide. One of the things to watch out for when nesting channel routes is the path to the route. When writing a child routes inside of this array, the way we write the path is also important. If we add a forward slash at the beginning, the path will be treated as a root path. I'm going to add an example just below, so forward slash history would leave us with our URL such as pizza planets.com, forward slash history. Alternatively though, if we didn't have the forward slash before history, we could have simply typed in history inside of our path. This will be pizza planets.com. This would take into account the parent's path of forward slash about, then followed by history just afterwards. This is two different approaches all dependent on the forward slash inside of the path, depending on which way you want to construct the URLs. I'm just going to remove these two examples inside here. Then also are a comma to separate this about link. We can also add our contact link two, but this one is at the root level along with our menu on home. I'm going to add this as our third item. A path is forward slash contact and the components is for contacts. Camera at the end. Then also our admin two. This is not controlled by a menu link, but we can still access this using the forward slash admin inside of our URL. Then the components of admin and a comma at the very end. We then need to import our components which you want to use, which are the child components and admin and contact. Let's duplicate this a few more times. The menu which changes to be admin. We also need to import the About page, we also need contact. We also need history, delivery and ordering guide. Delivery and finally at the end we need the ordering guide. Once this is done, give this file a save and head over to the browser. Let's check out our home routes. We have our menu still working, the contact-us. We can test our forward slash Admin. This is all working too. Then finally we have the about us link which has a child component. If we click on this, none of the child components are visible. This is because the router view component, which we have, if you open up the app.view. This is the router view component which we currently have. This renders out the component to the screen. But it only renders out the top level routes. To display a component of HL route, we need to add a second nested router view component. I'll show you how to do this in the next video. 28. Nested router view: As we discovered in the last video when we click on the About Us link inside of our menu we see only the empty About Us component and none of the child components are displayed. This makes sense because this is the parent component, and we want to have control over how the child routes are displayed. To switch between the child routes, we need to go over to the about components and then do two things. First, we need to add some menu links to switch between the child components. Then to actually display these components, the about component will also need its own router view component too, which we can add underneath the menu. Let's start up inside of our div, inside the main templates. We want to begin with a level three heading with a tilde on either side. Then the text of, "Click on the links below for more info." The navigation tags, which is going to nest inside an on order list. This on order list is going to contain our links. For this, instead of the list items, we'll use the router link, making sure it closes off just below. Inside the opening tag, we can add our two prop, and its going to link to the forward-slash history route. We can add our tag which is going to be a list item, and then nested inside a link. We don't need the href since the view router is going to handle our routing. Instead, we'll just add a class which is going to be nav link. The text inside of our history and this is our first child routes. I'm going to copy this. Remember we had three links. The second one is going to be for the ordering guide. This is going to link to the ordering guide. Then the text of ordering guide too. Everything else is fine. The third and final link is going to be for delivery. Change the text and also the two prop, save this file and let's click on the About Us link on the forward-slush about routes. We now see our level three heading and our menu links below. The styling needs a bit of work too, but we'll come back to this. If we click on the links of history, ordering guide, and delivery, we see the URL is changed up at the top two. These links are changing the URL, but we don't see any components displaying just yet. To see them, as we mentioned before, we also need to add a router view to show the selected link just below the menu. Just after our nav, we can add inside a router view. Close this off. Save this. There we go. There's our delivering info, the ordering guide, and the history components. Finally, we can finish this off by adding a little style in. First, we can center the level three heading up at the top. Let's go back to the About.vue. Underneath the script we can add the style tags, tag is the h3. The text line is going to be center and this now pushes this over into the middle. Also, the links need some work too. Rather than repeat the styling for these links and also the main header, I'm going to add these as global styles. I'm going to place these in the App.vue without the scoped keyword. This is just my personal choice to add them here in this file. It will also work in any of our file too without the scope tag. Let's start with the body. I'm going to set up the font firmly of Crimson text. With a plain setit fallback. The margin can be reset to zero. Also, the font size of the body to be 1.5em. Next up the links. The text-decoration to be none. The color we're going to inherit underneath this, we can target the on order list. I'm going to set the display type to make use of the flexbox, so we can justify the contents in to the center. We can reset any margin to be zero. Also, some padding for our on order list of 10 pixels on the top and bottom and zero on the left and right. A background color. I'm going to use the hash value of f1e6da. We also need to remove the bullets from our list items. We can do this with the list-style by setting this to be none. Save this. Over to the browser. We also need to add some spacing in-between these links. Here we used a tilde inside of a span element. I'm going to add some margin around this and also use the same tilde icon and just below too. Let's go back to the About.vue and open inside of our template. Just after each router link, we can add a span, the tilde icon, and copy this, paste this just after our ordering guide. I'm working at these as global styles back in the App.vue. Just after our list item, we can tag the span and set the margin of zero on the top and bottom and five pixels on the left and right. Over to the browser. There we go. There is still small styling to add to our project but we will come back to this later in the course. With our nested routes now working, I will see you next time where we will cover using name routes. 29. Adding names to routes: If we head back over to our main.js, where we've declared all of our routes for our application. All the routes we've created so far have used a string to specify the path of the URL which you want to navigate to. Such as forward slash, path slash menu, path slash contacts and also about. This works perfectly fine and there is nothing wrong with using this approach. There is an alternative, however, which may be more convenient, especially for longer paths. This alternative is to add a name to the route. We can do this inside of the routes objects, or we need to do is to add the name option. Then inside here we can specify as a string and name which you want to give to this. I'm going to add to the home link and then a comma just afterwards. These names are totally up to you. Just go with something which best describes the route willing to consume. We can also add this to all of our over objects too, paste this in. The second one is going to be for the menu link. The next one, this is for the contact link. Then the admin link. We can also add this to our channeled routes to, this is not just for our top-level routes. We can add this for our history link, the delivery, and also for our ordering guide too. Now all we need to do is save this file. I'm going to make use of these inside of our menus, starting with the header.view. Inside of our router, we already have some form of name routes, which was set up early in the section. Each one of these names are dynamically binded to our dates property. To make use of the names we just setup in a router. Inside of our quotations, we need to pass this in as an object, passing in the name where the value is the name of our link. Next, we can do the same for all menu link passing objects and set the name as a string. Then we could do the same for the contact link and also about. These also need the dynamic colon to bind this just like before. But we can now remove the date property between those script tags since we no longer need this. Let's clean this up. Then we can go to the about.view, where we also have a menu to these are not currently dynamic. We need to add to the colon, to bind this. We could remove this and out of objects with the name property and the name value, which is going to be history link. The same for the ordering guide, just below. Fasten our object with the name. This was ordering guide link. The delivery at the colon, fasten our objects. This one was delivery link. This should now be all of our links taken care of. All that we need to do now is to test our links, is still working in the browser. Let's go over. We have the home, the menu, contact, and browsers. The about link is working. Let's check this out in the header, this just needs to be about, say this. The about link is now working. We can test out the nested routes. History, ordering guide and delivery. Our URL is updated with the correct URL. Even though we now referencing this by a name. This is how we can add names to our routes, and next we will look at changing routes without needing to click on links by using router.push. 30. Router navigation methods: All of the navigations we've performed so far, have been a result of using the router link component to take us to the path which we specify. There is also an alternative way of doing this, however, by using code to navigate programmatically. If we go over to the home.vue components, inside the components folder, we added a button on line seven here to take the user to the menu. We've not yet added any links to this button yet. But we can also use the router to push to any location. I'm going to begin by adding a click listener to this button inside of the opening tag. So use [inaudible] click. I'm now going to use this to figure a method which I'm going to call Go To Menu. Scroll down to our script. Then we can set this up just after our name property. We can set up our methods and our method name of Go To Menu. We can access any method which has been provided with the vue router inside of this vue instance using this.$ router. Remember anything prefix with this $ indicates that this is native to vue.js, or in this case the router package rather than a custom method we have created ourselves. Here we can take a look at some of the navigation methods provided by the router. Vue router gives us the option of navigating back or forward by accessing the browser's history. It does this weird router.go, and this is the first method which we are going to look at. This takes in a single argument to declare how many pages we want to move. Positive numbers will move the pages forward in the browser's history. Negative numbers, will go back one page in the browser. We can test this by going over to our application. So give this a save. Let's click on the "Menu," and let's click on "Home." Now if we click on the left sided button, it should take us back one page which was to the menu. Let's try this one more. If we go to the about link and then home, click on this button it should take us back to the About Page. This number can also be more than one too, if you have a use case for this. Another method which is available on the router is router.replace. This is used to replace the current URL with the one which we add inside these brackets. So if we wanted to go to the menu, we could add a string of forward slash menu, over to the browser. Let's go to the Contact Us, then to "Home." Click on the button. This then pushes us to the menu page. Or just like we looked at in the last video. We could also pass in an object and using named routes by passing the name property. Then our menu link, which we setup. Let's give this a go. Contacts, home and this still pushes us to the menu. However, there is one potential drawback when using this replace method. I will show you now. If we go for example, to the About Page and then click on "Home," click on the "Let's Order" button. If we then navigate back using the browser's back button, this then takes us back to the About Us Page rather than the homepage which was the previous components. The reason this happens is as the name suggests, the browsing history is replaced rather than added to. If we want this link, we are going to be added to the browser's history so we can use the back buttons in this way. There is another method available to us called router.push. This is also used to navigate to a different URL. But the difference is the routes and are pushed onto the browsing history rather than replaced. Let's give this a go. Changes to be push. We'll do the same as before, we'll go to About, to Home, click on the button, which takes us to the menu. Now if we go back, we're now take into the home component rather than the About Page. Both of these ways are fine to use, but of course, it depends on the behavior which you want to achieve inside of your app. 31. Global navigation guards: Sometimes when navigating between routes, we want to perform an action even before the route is navigated too, or just afterwards. As an example, we will be setting open alert to load up just before the admin page is navigated too, which will tell the user this is a restricted area, and they will first need to login. Also, when leaving the admin, an alert will also pop up, which will tell the user they'll be automatically logged out when leaving this admin area. This is for security reasons. VueRouter hazards covered this use case by providing us with navigation guards, like the Vue instance hooks. Navigation guards allow us to hook into certain stages of the navigation. Also, we can add to them either globally for our whole app or apply them locally to certain routes. Let's start by taking a look at the global before-each guards. I'm looking at this in the main.js. After our router here, we can access our routes available and then access it before each hook. This is going to take in a function, and it also takes in three arguments, which we'll take a look at in a moment. Also, as this is a global hook, the code which you add in is executed each time any routing action is triggered. For example, look at adds an alert who detects off navigation triggered. If we now save this and go over to the browser, we see the alerts pop up straight away, and also for each navigation link which we click on. This works fine, but notice there are no page components on the screen. This is because the routing action will not be completed until we call a function called next. Next is one of the three arguments which we can pass into before each. The first one is to, and this is the route which we navigate into. The second one is from, and this is the route which we're leaving. Then finally we have the next function, and it's this next function which you can pass in to complete the navigation and load up the page components. If we now go over, click on the alert, the routing action is completed. We then move to the page components which we've clicked on. This next function will tell the Vue router to move on to the next navigation hook, if there is one available. If no more hooks are available, then as we've seen here, the navigation is unconfirmed. We can also stop this navigation if we have a use case for this, by passing in a Boolean value of false. This will then stop the page components from loading up. This will be the same for each navigation routes. We mentioned before we also have access to the to and from data, which we also passed in as arguments. To see these, we can pass in a console log, taking in the to value, and we can see exactly what data is provided here. So let's do this over to the browser and right-click on Inspect, and then click on the console. Also, as a side note, if reduced again, no console error message in the browser. This is a setting in ESLint. ESLint is provided when setting up the Vue CLI. This is used to check the code for errors. Sometimes by default, when using ESLint, the console messages will provide an error. So if you need to disable this, head over to the package.js on file, open this up, and inside here we'll have an ES named config objects. Inside this object, if we scroll down, inside of the rules objects, we need to add a name value par of no console and off. If you add this, save the file and then restart the development server. You should then have no problems viewing the console, unable to continue with the rest of the course. Also, again, with ESLint, we may need to remove any unused variables slash remove from a next, and take look at the object inside the console. Let's, for example, click on the menu and open up this object which is provided from before each. So this is the path which we navigate into. We're going to the menu. This is the router name. We can see if any parameters have been passed in, and we have access to any of these properties inside of our code. So rather than using the console log, for example, you could add an if statement to check if to and access the path is going to be equal to the screen or forward slash menu. If it is, we're going to continue on to the routes and we'll say else. Next is going to be equal to false. This will now allow the router to only go to the menu components and any of the pages will be blocked. Since we now making use of next, we can also pass in the rest of our arguments. So from next, let's say even head over to the browser. So now if we click on the home routes, we don't see any components. If we click on menu, we've allowed these to load up since the path is equal to menu. Let's try contacts and this is blocked. The same with about us, and also returning back to home along with before each. We also have available the after-each global guard to. As the name suggests, this is called after each navigation is confirmed. This cannot affect the navigation because it's performed after the navigation has been completed. Therefore, it doesn't receive the next function as an argument. So calling in next function is not needed too. We can see this again by passing in an alert, and any text inside here, we'll say after each, save and over to the browser. Again, we may not use need to argument, so we may need to remove these. We see the alert, click on Okay, contact us, and this is loaded okay too. So as you can see, even without the next call, the pages components is still rendered, and we see the alert displayed as expected. This is a never useful hook which may be needed if we need to perform an action after the route has finished taking place. Again, these are both global guards which are going to be used for each route. In the next video, we're going to take a look at component guards, which will only affect the components we're navigating to and from. 32. Component guards: In the last video, we looked at global navigation guards, which will affect the whole of our application. An alternative to this is is to only add a guard inside of a component. This way, only the components being navigated to and from will be affected by the guard. The first thing I'm going to do is to remove the global guard from the last video inside of the main.js so, the alert doesn't pop up for each navigation. Then I'm going to head over to the admin.view components and start with the components folder. I'm going to add a guard inside of this components. I'm going to begin with the before route enter guard, and let's add this up just after our components. This can be added anywhere on the view instance, and the name is going to be before route sensor, which again is going to take into from and also next as arguments, add a comma to separate this from the methods animals to add [inaudible] property just above to work with. We can return some data. Let's add a name, property and add your name inside of here. Before route enter is called before the route, which when it is component is confirmed. Here I'm going to create an alert which is going to say hi to the user. We have the user's name just above inside of the dates property. I'm going to add this as a template string inside the back ticks. You can add inside our variable, which is going to be this name. Discard is inside of the admin component only. Let's give this a save and head over to the admin linked to see this action. We may also need to remove our free arguments for this to work. We click on any of these links, we don't see the alert. Let's try going out to the localhost slash admin routes. We don't see the alert which would just set up. Let's go to the console and take a look. We see a red error message cannot read property name of undefined. This may not be immediately obvious what the problem here is. There is in fact nothing wrong with how we setup the name property. In fact, the problem will occur if we tried to access anything from our view incidence. The reason behind this area is because the guard is called before the component has even being created. This is why we don't have access to the data on our view incidence. If we need to add our view instance data inside of this hook, we need to add a work around. To do this, we need to pass in a call back to the next function. We again need to add into from also next. We can pass in the next function, which is going to add a callback function, which will run once a component has been created. He says about function inside here, which I'm going to add as a narrow function passing in VM, which is short for view model. VM can be any name of your choice. But when using view, it is pretty traditional to use VM as a name inside of this callback. Here we have access to the same view instance using VM in the place where we usually use this. Now we can grab our alert. We can bring this down into our callback function. We can then replace this with VM, and this should now work. What we're doing here is basically creating a callback function. Once the navigation is confirmed and our component has been created. Once the component is created, we then have access to our view incidence data and we can now access is inside of this call back function. All we need to do is replace the this keyword with VM. Let's save this and head over to the browser. Let's reload. We now see the message of Hi, Chris. If you go to any other routes, this won't work since we've only said this on the admin components. Now we have this working and we can move on to the next video where we'll take a look at guardian individual routes. 33. Guarding individual routes: The last type of guard I want to show you is the before enter guard, which can be added directly to where we define our routes in the main.js. Before I create this, I'm going to remove any unneeded code for our application. So in the admin from the last video, we can remove before route enter, and also the data property which we set up for this. Save this file and over to the main.js. I'm going to add this new navigation guard to the admin routes. So to make this more readable, I'm going to add these on two separate lines, separated by a comma just after our components we can add the before enter, guard beforeEnter works just like the global before enter guard and also takes in the same free arguments of two from our next. We said the server as a function. I'm going to add an alert inside here, which is going to send a string of text to the user to say this area is for authorized users only. Please login to continue. After our alerts, we also need to pass in the next function to complete the navigation. Say this are now if we go over to the browser, and first of all, we can test the individual routes inside the header and we don't see any alert for these four links. If we now go to forward slash Admin, where we'll apply this navigation guards. We see our alert has now popped up. Of course just popping up an alert is not secure its own. But later on we will hide the admin area and only displayed to logged in users. We will also later on, are they before route leave god, inside of the admin components for when leaving the admin area. Say automatically login out the user when navigating away from the admin. 34. Defining scroll behavior: When we all tune, we may want to preserve the scrolling position. We will ask them when revisiting a page, or alternatively, we may want to scroll to a sub-position on the page when navigating into it, even if it is only at the top of the page. Using view router, we have full control over the scrolling behavior. This is also dependent on the router mode being set to history modes. We already have the history mode enabled in the main.js, so we can take advantage of this. The first thing to do over in the main.js, is to add the scroll behavior function to the router instance. Let's take a look, inside of our router here, I'm going to add the scroll behavior. Inside of the brackets or the parentheses. Just like the gods we looked at, it takes only to and from route objects. Also an argument we pass in a cold, say position, which is the position, say by the browser when the back or forward buttons have been used. Say position. Inside of this function, we could define our scroll behavior. Probably the most simple way to do this is to return an object. I'm passing the x and y position, which you want to scroll to when navigating to a page. We can return our objects. We can set the exposition to be zero and then set the y to be zero too. Using this setup, each time we navigate to a route, the page will be scrolled to the very top. You see this pattern in action. Let's change the y-axis to be 200. This will load up a new page, 200 pixels from the top. Let's save this and of course we need to remove our free arguments so you don't get any Linton problems since we're not using those. Let's go to home. We don't have enough content on this page to scroll down. Let's try the menu and you can see we are 200 pixels from the top. Alternatively, we can pass in a CSS selector in place of coordinates. Let's go for a selector and let's open up the menu components. We can set the scroll behavior to scroll down to any one of our CSS selectors. We can choose a button, we can choose a class. We can choose any ID or simply an elements by its name. I'm going to go for the shopping basket. Lets go for the class of baskets. Inside of the main.js. We can keep our object. What replaces with a selector, which is going to be a string. Since this is a class, we can target this with the dot and the name is baskets. Give us a safe. Let's go to home. Then back to our menu. Now you can see the browser has been scrolled down to the basket location. This works for any selected two just [inaudible] when using CSS. Remember we mentioned the safe position parameter which you passed in. This saves the scroll position when the browsers forward and backbones are used. Lets now take a look at how we can use this. Let's pass in our arguments once more, which was to, from and a safe position. I'm then going to add an if statement. The if statement is going to check first if there is a saved position. If saved position is true, we're going to return the saved position. We have one available, we're going to scroll to this position. If not, we're going to add the else condition where we are simply going to return an object where we set up the x and y position to be zero, just like we looked at before. So to see this in action, we need to go over to the browser and navigate between a few pages. So first of all, let's go to the menu and then scroll down to the very bottom. We can then use the Back button and then the Follow button to return back to the menu. I'm an opposition right at the bottom of the page. If we try this again, if we scroll up just a little bit, just so we can see some white space in the menu. If we try going backwards and then forwards the browser, saved position, returns us to exactly the point where we were in the menu. The last one I want to show you keeps the saved position, just like this one which we just looked at. However, it works when switching between components using menu links, rather than just using the back or forward buttons in the browser. We can again use an if statement. But rather than the saved position, we're going to use the two arguments and select the harsh, and this will first check if the route which we navigate into has a location hash saved. If it does, we're going to set the selected to be equal to the value of this hash. We can return inside the curly braces, a selector just like looked up before. On the selector we're going to add is to.harsh. We will also need to remove the unused parameters so we don't see any errors. This notion, we do need to add more content to one of the other pages. I'm going to go to the contact and just simply copy all of the contents from the contact rapper. Being shoots, keep the surrounding div, and paste this in a couple more times just to give us some more content inside of contacts where we can scroll up and down. We close the sidebar back over in the main. We can also remove the L section here, this file save and over to the browser. Now if we have the contact and menu with some content where we can scroll down to, I'm going to scroll down to just above the flag. We have this as a reference point. Switch to the contact page. We see the browser position has been saved back to the menu. This will keep the saved position between components. It won't work if you go to the Home, for example, or the about us because we don't have enough content. Scroll down too. But this gives you the idea of how it works anyway. This is it now for this video. Just to wrap this up, I'm going to reinstate the contact page just to harvest content only once. Give this to save and restore this back to normal. These are the options available to us to control the scroll behavior. Next, we'll refactor our routes by moving them to their own file. 35. Re-factoring our routes: Inside of our main.js where we've created our routes. This routes array is pretty manageable at the moment. We don't have too many setup. But you can see how it can really clutter up our main.js file especially if adding more navigation guards or child components. We can take all of these routes out to the main.js and place them in there on file, which will tidy things up and make it more organized. Doing this is a pretty easy setup. First, I'm going to add a New File into the Source Folder. I'm going to add this into the root of the source and call this the routes.js, then back over to the main.js. All we need to do is to grab the full routes array. From the closing square bracket, all the way up to our constant, I'm going to cut this out. All to our routes, we can now paste this in since it's router. If referring to components, we also need to import these too. We can grab these, and Visual Studio Code will make this a different color. We can see we no longer use these. I'm going to cut out all of these components which no longer needs, place them in our routes.js. Next up, we need to export this object too. Since this is now in its own standalone file, we also need to export this file, so we can import it back in our main.js. With a matching name of routes, which we gave it just here. The location as a string is dot slash and then routes. This is all we now need to do. We can now go over to our app and test if the routes is still working okay. Let's try the menu contacts, the about, and also our child routes are working too. This is something which is not necessary on small applications, but it's something which can keep a larger or a growing application more organized, and it's also something which is pretty simple to do. 36. Named router views: If we head back over to the main app the Vue file. Inside a here we have a router-view. We have so far looked at using this router-view to switch between components. Also, how we can use the router-view components to display child routes inside of the above components. We can also use multiple view routes components inside of our app. This is so we can display multiple views on the same page, rather than just switching between single components. For example, inside of this app the Vue file, we have this router-view component to switch between the main contents. We're not restricted though to only one outlet, we can add as many router-views as we want by giving them a name. We have already set up some information components which we use in the about. We have the ordering guide, the delivery information, and the history. This would also be ideal to display on the homepage too by using a new router view. Let's set this up just below our current router-view. I'm going to use this to display these three components. Let's set up a div with the class of info_block_wrapper. Now, to display our free information components, we can add more router-views, but this time with the name attribute. The router-view with the opening and the closing tag. Inside of the opening tag, we can then add the name and we want to set this name to be ordering guide. Then duplicate this two more times. The second one is going to be for delivering, and the third one is going to be for history. Save this. If we head back over to the browser and click on our "Home" link. We don't see any components currently shown on the screen, this is because we first need to add them to our routes. So let's head over to our new routes.js file. Since our home links will now be displaying multiple components, we need to change the component of property just here, have an s on the end to make these components. Remove the home link. This is now going to take in an object where we can add the components as key value pairs, just like we do when registering a components inside of the view instance. First, we add a default components, which is going to be the home. This is the component rendered in the router-view with no name. This is the original one we had just up at the top here. This will keep it just as we had before with the home components. We can then set up our free router-views just below all with matching names. The first one was the ordering guide. We want to map this to way components called ordering guide. The next one was for delivery. We want to map this to way components called delivery. The third one was for history. Let's see this over in the browser. Back to the homepage. Our free components now taken the place of our named router-views. Also the default home components is taking the place of the router-view, which doesn't have a name. This also needs a little work with these styling too when we created the ordering guide, delivery and history components. If we take a look at these, we can open up any of these. Inside of the template, we added a class of info_block as the wrapper, and also a class of info_block_contents, which is for the title and also the image. If we go back over to the app.vue. We also surrounded these free components in a class called info_block_wrapper. We can target these classes in the CSS, starting with the smallest screen view. Down at the bottom, we can target the info_block_wrapper. This is a wrapper for our free outlets. I'm going to set the display type to be flex. We can set the flex direction to be column on the smallest screens. So these are stacked. Next up the individual info_block. This is the wrapper for each components. I want to give this a background color, which is going to have the value of f1e6da. So margin, so 10 pixels on the top and bottom to add some space in and zero on the left and right, some padding on the inside of the div of 10 pixels. The number can target the info blocks and level 3 heading. If we go back to the ordering guide, this is the title at the top of each block. Info_block, we can target the level 3 headings. All I'm going to do here is set the text line to be in the center. We can also target the info_blocks_content. This is the section just below the title, would detect son also the image. Once you set this to be a display type or flex, so we can align the items into the center. Then finally for the small screens, I'm going to set the info_block image. All I want to do here is to restrict the width to be 30 percent. Let's take a look at this in the browser. We can shrink this down to the smaller view. This looks a little bit better on mobile devices now. If we stretch the browser out to the desktop size. We now need to add a media query to target this. I'm going to set up the media query target the minimum width of 900 pixels. Our media screen. Also the minimum width be 900 pixels. Let's start with the info_block. Setting the width to be 100 percent. The info_block_wrapper, which is the main wrapper for all, free of all components. We can set the flex direction or override the flex direction from column to be row so these all aligns. Next up, if we take a look inside of the browser, we now have these setup across the row using the flex box. But we want some spacing in between each one. To do this, I'm going to select this "Info_block" in the middle. We can target this one by using the nth-child. Back over to the CSS and target the info_block, and then the colon. We can target the nth-child, which will select any one of these which we pass in. We want to select the second one which is in the middle. Then all we're going to do is set some margin to be 10 pixels. Give this a save. Now, this is added some 10 pixel spacing around this components. Next up inside of these three components, we're going to have the text on the image stack vertically. We can do this by setting the flex direction to be column and also align these into the center. Let's go for the info_block_contents. We can set the flex direction to be into a column and also align the items into the center. Save this. Next up the image. I'm going to give this a maximum width of a 100 percent. The info_block image, the maximum width, going to restrict to 100 percent. Finally, I'm going to use the flex box to reset the source order. So these are alternated by moving the image above the text on the second child. Let's use the same selector that we used before using the nth-child. We can add this in. But this time we also want to target the image. We can reset the source order by setting the order of the image to be negative one. Save this. Our free components and now alternated on the larger screen. If we shrink back down to the mobile view, source order stays exactly as it was since this is set inside of a media query. This is now the end of our routing section. You can see there is a lot more to routing than just switching between pages. I hope this section has given you a good idea of what is available. In the next section, we're going to move on to stay management using View x. 37. What is Vuex?: When working with Vue.js projects, we can manage the application state in a number of ways. When sharing a passing state between components, there are multiple ways we can achieve this. Data can be passed from a child to a parent components using Custom Events, and from the parent, the child by passing props. We can also improve on this by adding an Event Bus. This Event Bus acts as a single central store, told our states and is basically a separate file containing a view instance, which we can had our state to, and import to each component when needed. It's a great solution for smaller to medium-size applications. But a single file like this however, can quickly become really large and more difficult to maintain for large projects. This leads us on to the subject of this section, which is the UX. UX is a state management pattern plus library for managing our states, with the state being basically the data which is held in our components. It's ideal for managing large projects, and it's wrote by the Vue.js call Team, so integrates perfectly into your Vue.js projects. Like the Event Bus, it also acts as a single central stall for our state, but it has some benefits over the Event Bus. For example, allow you access a single source for our states. We can still break it up into different files on modules to organize our code, and we'll take a look at this soon. We don't use props and events with Vue.UX. We use different methods which will also cover these dedicated methods, make it easier to track and manage changes made to our states. Use an Event Bus if multiple components keep making changes to the stall using custom events, these changes can be hard to track. We may not know which component made which change, and this may cause problems updating. Also, as we will see in this section, not only does Vue.UX act as a single data source for our application state, it can also be used to gather required data from other sources. We will be using it to hold our component states along with our data from Firebase. This makes our store one single convenient place to access all of the data which we need. With all of this being said however, if you build in a smaller or a medium-sized application, Vue.UX is not always the best solution. It can often be a case of adding it when you feel it's needed or when other solutions are causing problems. Now we know what Vue.UX is, let's get to work on adding it to our project. 38. Installation and file structure: If you want to read more about Vuex, you can head over to the homepage, which is vuex dot vuejs dot org. But I'm going to jump straight into getting this setup inside of our projects. Getting Vuex setup inside of our app is not too difficult. If we go to the installation, just like when we install the router, the CDN links available if you prefer but since we use an NPM, I'm going to install this over inside of the terminal. Let's open Visual Studio code, wants to close down the server and then install the command which is npm i, and then the package name, which is Vuex. And then give some moment to install. Once this is done, we can restart the development server with npm run serve. We can add this to our files and folders. Now, they want to say straight away that Vuex does not enforce any certain structure to all files and folders. We are free to handle it exactly how we want. It is common nodes have one main folder for our states inside of the source folder called store. Let's do this now. Let's go to the source, create a new folder, name this store. Then inside here we need a main JavaScript file, which I'm going to call the store dot js. This will be the main file for our store, and it can be any name which you want. You may also commonly see this called the index dot js. I'm going to call my new store to distinguish it from any other index files. Then inside of our store file, we need to import both Vue and also the Vuex modules, so import Vue from Vue and also import Vuex from Vuex. Then just like when we installed the router, we can add Vue dot use to make Vuex available in all of our files or modules. This next section should also look familiar too, from when we added the router. We need to add a new Vuex store, and also export this so it's available in our files, so export const store and set this to a new Vuex dot Store, capital S. Inside here we pass in an object and it's inside this object where we can set any initial state. For example, if you had a game where we updated the player's score, we could add a state property here for the score and initially set it to zero. Then one or more components could update the score during the game. The other file I want to add too is the main dot js, so let's open this up. We need to update this into our main file, just like we did with the router. First we need to import the store. This is named export and the file path is dot slash into the store. Then the file name which is store too. Scroll down, we can then register our store inside of our view instance. Just below the router. I'm going to add this here, followed by a comma. And this is our store now registered with Vue, back over and install dot js. I'm going to set things up by adding a initial state objects. Inside here. All the state object works a bit like the view data property, where we can set up our variables and update them from our files. With this now all set up, I'm going to leave this video here. As we go through this section. There will be a lot more files and folders added and the low more added to the stall. But for now, this is the start setup and registered to be used and will begin to access data from our store in the next video. 39. Initial state and accessing the store: With our new Vuex store now setup, it's time to add some state to our store and see how we can access it from within our components. Just before we do this, we have an error down in the console, and this is because our Vuex needs a capital V to mark your import at the very top. We now start with retrieving pizza data from our Firebase database along with our customer orders. Until we set this up, however, I'm going to simulate this. If we go over to the menu.vue components, inside here, if we go down to our data property, we have our sample data here, which is get menu items. I'm going to cut out all this section from our components and then move this over to our store. Make sure you grab the right section. Get menu items, leaving just the baskets and also the basket text into our store. We can now paste this into our state object. Then I'm just going to change the name to simply be menu items. This means, our data is now taken out to the components and placed inside of a central store for any component to have access to. As expected, if we go to the browser and then go over to the menu components, click on the menu link here, the menu is missing because we removed the data and placed it into a different file. How do we access these store from inside of this components? Well, if we go back to our menu.vue components, we can now have access to our store inside the computed value. I'm going to call this get menu items, just like we had before. Inside here, we're going to return this dot $ symbol store. Then from our store file we're going to access the state objects, and the pizza state, which we called menu items. This name of get menu items, also matches our loop. If we scroll our loop, slip above basket, and here we are, inside of the menu, we have get menu items. We just need to add a comma after the computed values. Say this, and back over to our menu. We now have the menu data now in place. This data is now accessed from our central store, rather than it being restricted to one single component. When data install updates, this component and any others, which access in this menu data will also be updated or re-rendered. If we make a quick change to a pizza name back in the store.js, let's go down and change the name of this, gives this a save, back to our menu. We now see this immediately updates. Finally, we also access the same menu items from within the admin screen too. Let's go to the admin.vue. We can set up a computed value, just like we did it inside of the menu. Setup our object and add the comma just afterwards. The name again is going to be the same of get menu items and we're going to return our store because access this dot $ symbol store, our state objects, then again, menu items. Scroll it up. We can now use this to create our dynamic data inside of the menu table, but from the very top, just underneath the menu title, if we look for the table body, we can create a V for loop. We're going to loop through the get menu items. So item in get menu items. We can also bind a key and the key is going to be equal to the item dot ID. Now we can use this item to replace the hard-coded value of margarita. Inside of the double curly braces, we can access the item.name and they should be now repeated since it's a loop for all three of our items, inside of our store. Over to the admin. Let's scroll down to our menu. Now we'll see our free items pulled in from our central store. This is one way to access data from our store. Next we will look at another possibly improved way, which is by using getters. 40. Improving store access with getters: In the last video, we accessed our central store directly using a $store.state.menuItems, just like you see here. There is a better way to do this, however, and this is by adding getters to our store. As this name suggests, we use them also to grow up data from our central store. But you may already be thinking we are already getting data from our store. So why are we using a getter? The reason is because you can do so much more with getters, when we access the state before directly using $store, yes we got the data which we wanted back, but as an example. What if we wanted to do something slightly more complex, such as faction orders from the store and then filter these orders to only show the orders which are completed. To do this, after we fetch the data, we would need to perform this filter action inside of the components computed property. If only one components wanted to perform this filter. This is not much of a problem. However, if multiple components would access the same filtered data, we will be having duplicate code through out our App. To fix this, we use a getter to fetch the data we need from the store, then perform any action we want, such as a filter or calculation. Then the components will receive the final or the exact data which it needs. I think a getter is just as simple as adding state to our sore. If we head over to this store.js , just after our state objects and scroll down to the very bottom, add a comma and setup our getters object, just like I our state. We then add the name of our getter and I'm going to call this "getMenuItems." This is going to be a function which receives the state as an argument. We then use the state to access any piece of information which we want. So we want to grab the state.menuItems from just above. We can then use this getMenuItems getter inside of the menu components, lets head over to there "menu.vue". Then all we need to do, rather than accessing our state, we're going to access our getters objects and the name was getMenuItems. The other getter which we need is to get the number of orders which we have. For this, we need an orders array inside of our state, so back here to store, right at the very bottom, just after our objects add a corner. We're going to initially set our orders array to be empty. This is empty at the moment, but later in the course we will sync this information with firebase, to pull in the orders from our database. Using this, we can now set up a second getter, called Number of orders. This set up just as above. It takes in the state as an argument of our function and we can access the state.orders. Since we want them to know the number of orders rather than the contents, we can access it with the land property. The number of orders is part of our admin screen. Therefore, we need to add this to the admin components. Let's go to there, down to the computer property. After I get menu items, we can add our number of orders where we're going to return this.$store.getters.numberoOfOrders. Also while we're here, we can also change the get menu items above to also use the getter. So getters.getMenuItems. We can now use a number of orders up in our templates. If we'll look for the current orders, we have a hard coded value of five. Inside of the double curly braces, we can access our number of orders. Give this a save and off in the admin, reload the browser. We now see the currents orders is set to zero. As we mentioned at the start of this video, when using a getter, we can do pretty much anything we want to the data before we pass it to our components. For example, we could do something simple, such as the oddest land plus 10, and this is updated inside of our component. Or we can do something much more complex, such as formatting or validating data even before it reaches our components. We know how to access state from our store. Now is a good time to move on to looking at mutations that change the state within our store. 41. Changing state with mutations: When dealing with state so far in this section, we've looked at how to retrieve the state from our central store, both directly and by using getters. When I want to move on to changing the state inside of the store, and the correct way to do this is by committing a mutation. Mutations simply change data inside of our store. They work in a similar way to when we omit an event. But rather than emit data to a component, we can make changes to the store instead. Also, mutations follow views reactivity rules. This means once we use a mutation to change the states, all of the components watching the state will update automatically too. Inside of the menu on the "Basket", we have this "Place Order" button, and we also have the empty orders array inside of our central store. This would be a good use case for a mutation to be able to mutate the central store by pushing the contents of the order. When we click on the button to this orders array. Just like getters, we set up our mutations inside of the store. So I am going to add this as an object separated by a comma. So it's about mutations. Then we can add the mutation name. This mutation will add an order. So I'm going to simply call this "addorder". The mutation accepts the states passed to it as the first argument, just like it does when you sneak getters. Then we modify the state how we want it inside of this arrow function. As an example, if our orders were a number of orders just like this, if we set this to be one, we could then set the state, though orders to be one more with ++. Now to call this mutation, we need to go to our "menu components" and add a new method. So we head over to the "menu.view" and I'm going to call this method "add new order". If we take a look for the "Place Order" button inside of the opening tag and wants to add a "click" listener and set the sub to be our method called "addNew order" scroll down and we can create is just below. Inside of our methods, we have quite a few. So just after decrease quantity, we can add new order. So the first thing we need to do is to actually access the store. Just like before we can do this with this.$store. We then need to commit the change by using the commit method. The change we commit is the name of the mutation we just created in the store, which was called "addorder". We pass this in as a string, and then after we add the order, it would make sense to clear the basket inside of our components by setting the basket to be an empty array. This basket is just above inside of the dates property, which this array just here. So we need to clear this once the order has been placed. We can do this simply with this.baskets equals an empty array. Finally, we can also add a message to say our order has been placed. We already have a date property of basket text. Just blow this basket, which currently tells us the basket is empty before a user adds a pizza. All we need to do now is to change this data with a new message. So this stop basket text is going to be equal to "Thank you, your order has been placed." The next thing to do is to actually check if the value of the orders inside of our store has been increased on each click. We can now put this inside of the menu template. So I'm just going to scroll to the end, and we can add this anywhere inside of the double curly braces so it can access our store, this.store. We need to access the state, the orders, or to other projects, and into the menu, we see the value of one. Let's create a new order. Place order, we'll get the value of two. Let's try one more and the value of three. This is the most simple way to commit a mutation. We do however, want to improve on this by pushing the full contents of the basket to our orders array, rather than just incrementing number. To do this, we add what is called a payload. A payload is an additional argument we pass through the mutation, which contains the data we want to commit. You can think of this as adding arguments to a function, but we'll pass some additional information. We can do this back over in the "addneworder" method. Let's scroll down to this, and just after "addorder", you add a comma and then we can add the payload, which is the contents of "this.basket". Then over in the store.js, we pass this payload to the mutation as a second argument. So now instead of using state alone, we need to surround this inside of the brackets. Pass in the orders, the name of this payload is "up towards", but of course, it's best to be as descriptive as possible about the data which you will contain. Now, rather than incrementing the orders, we can now push the new orders to the array. We can then use the JavaScript push method, where we're going to push the orders, and we also need to change this back to an array. Gives us a save and this should now be a mutation work in. If we head over to the browser and into the menu, we see an empty array. Let's try adding some menu items and placing an order, and there we go. There's our margarita and our pepperoni. Which of the two items we added? Let's try a new one. Place the order, and we see the third pizza has been added to our array. So great. We can now see the store has been updated with the contents of our basket. It doesn't look too pretty at the moment, but this is easily fixed later in the course. The main thing for now is you now know how to successfully access the central store and also commit changes back to it. 42. What are actions?: So far, we've looked at using getters to retrieve state from inside of our central store. Also, mutations, which we just looked at, commit changes to our stall. Mutations do their job perfectly fine, but to have one thing to bear in mind, mutations must be synchronous. We can't add any asynchronous code inside of a mutation. If you are not sure what this means, with synchronous code, we have to wait for the task to finish before moving on to the next one. We have an asynchronous task, we don't have to wait for a previous task to finish first. These can run alongside each other. It does make sense that mutations run synchronously. However, if multiple mutations happen at the same time, we won't to be able to track which one most responsible for each change of states. If we were running an asynchronous code, we can't tell how long this process will take. Therefore, a mutation which was started first may not necessarily finish first. Having a mutation which runs synchronously means it needs to completely finish first before the next ones begins, and this makes tracking it changes more predictable. This is where actions come in. Actions can contain asynchronous code and are a bit like mutations. However, actions don't directly mutate the state, instead they commit a mutation. This means it will have the needs to run asynchronous code, such as requesting data from a server. An action will be used over a mutation. We can use actions whether they have asynchronous or not, and you can even keep things more consistent by always going through an action if you prefer, so this is the theory behind actions. Next, we'll put this into practice inside of our application. 43. Setting the user with actions: I am now going to setup an action to set the current logged in user. This user will be stored inside of our states. Let's add the current user property to begin with. Inside of the store.js, just below our orders array. The current user, which we're going to initially set to null. This will be initially set to null until a user is logged in, and then this will be replaced with an object containing the user details. I'm still going to perform the state change as a mutation. But as we mentioned in the last video, we will be using an action to commit this mutation. Let's first setup our user just blow add order, which we're going to call the userStatus, and we want to pass in the states and also the user, which will be our payload past when we commit this mutation. As an arrow function, this user payload will either be the details of the logged in user, if not the user will be null. In here we can add an if statement to check if the user is logged in. If it's true, we're going to update this state.currentUser with the value of user. If the user logs out, we can also update current user too. But this time we want to set the user to be back to null. This is one way of setting this up with an if... else statement or alternatively, we can use the JavaScript ternary operator to check if the user is equal to null. If it is, we can provide a condition where we set this date.currentUser to be null. If not, the alternative is we set the current user to be equal to the user passed in from the payload. Either way is completely valid and this is our mutation now complete. We now need to set up the action which is going to call this. We add the actions property into what we store. Just like we did with the gutters mutations. We set this up as an object. We can call the user status mutations, both when signing in and also when signing out too. Let's begin with the sign in action, which will take in two arguments. This function is going to be a sync and this first arguments which you pass in is the context object, and the second is the user. Setup our arrow function. The context object has a commit method. We can use this in just a moment to trigger our mutation. Well, first, if we go into the login.vue file and to our methods, we already have this sign in functionality just here. I'm going to move this over to our central store. If we put all of the contents between sign in, the catch section and also try making fewer. We just leave this curly braces on the outside. If we go back over to our store, we can now paste this into our sign in. If we scroll up when we use the sign in and password method, which is from firebase, we need to pass in the e-mail and also the password. When we call this action soon, the user payload will contain the e-mail and password so we need to change this to the user. It will contain the user details. This is going to contain our user information. We can store this inside of a constant called user data. This is going to store in the return value from firebase and we can use these to commit our mutation just above. Now I have this user data stored with you get back from firebase. We can now access our context object, which will allow us to access any of the methods and properties on the store's instance. For example, we can access our state with the context.state, or we can access any of the above getters, simply like this. We want to use the commit method, but we can also simplify this by using ES6 argument destructuring. Instead of grabbing the full context, all we want to do is to pull the commit method, meaning we could access this directly by name. What exactly do we want to commit? Where we want to commit a mutation by the name of user status. We're going to pass this in as a string. The second argument is going to be the user information, which we have back from firebase, which we have stored in user data and we can access our user objects. We also using this firebaseAuth referencing here too. We need to import this also at the top of the file. We need to import this as a name import. FirebaseAuth let me package location is from../ and then firebase. Now I know this may seem like a lot of steps to take just to set the user into our state. But remember this action step is added, so we have no restrictions on using asynchronous code with this action. All now setup, the final thing to do is to give it a try. We do this by dispatching the action from our components and this is what we will look at doing next. 44. Dispatching actions: In the last video, we'll move the sign in code from the login.view components into our central store. Now the action is complete. We need to dispatch it from our login components, passing in the user's email and password for it work. I head over to the login.view component and then scroll down to our sign in method. The sign up method is currently empty and we're going to begin working on this now. We can begin by removing the async keyword. This is because the function is marked as async in the central store and then inside here, we're going to begin by creating a user object which is going to store our email and password. We're going to setup the email from the data property, which you can access with the store email and also the password is available from the data property too. The next thing to do just after our user object is to dispatch in action, passing in the details as a payload. So access I our store which we're going to import in just a minute. We then need to call the dispatch method, which is going to take in the name of the action. The name of the action is signIn, and then we pass the payload which is our user object. It's good enough we don't need our firebase reference anymore, since you've moved this into a different file. Put in place, we need to import our store. The file path as a string is../. We need to go into our store, and then the name of the file is our store. Now we need to check this is work in by displaying the value of currentUser in our app. Remember currentUser was the name of a piece of state, which we set of in the store.js. This is a currentUser which is set to null as default and we know from earlier in the section, that to get the contents of our states. We need to use getters. Let's set the server for our currentUser. Inside of the getter is objects separated by a comma. I'm going to call this the currenUser and pass in our function, which grabs the currentUser from state. Now we'll have our getter. I'm going to add this to a computer property of in the admin.view components, so scroll down to JavaScript. You can now add this inside of the computed section. The name of currentUser. We're going to return the value, which is from this.$store, access the getters object, and the currentUser. Then inside of our template, we can output the value anywhere in our code as a test. I'm going to go up to the log in as section, and just output this inside of the double curly braces. See this contexter works by logging in and seeing our user objects. Let's go over to our admin where we can login. Scroll down, we're currently not logged in as anybody. Let's log in, using our email and password that was set up inside a firebase, sign in. Now if we scroll up, we see all of the user details which is held for our currentUser inside a firebase, but we don't need all of this information inside of our application. I'm going to filter this use information down to only display the current logged in user's email. We can see inside of this object there is an email key inside here and to only return this email address, we can make a small change to our mutation inside of our store.js. All you'll to do is to set the currentUser inside of the userStatus. We're going to set the currentUser to be equal to user.email. This will grab the email address from the user objects. Let's go down and sign in once more, click "Sign In," scroll up, and now we just have the logged in email address. We also need to move over the sign out method into the store too, inside of the admin.view where we have our sign out method. We can cut out the contents and move this over to our store. So have sign out, describe all the contents. We can take this over to our store.js, which is going to be an action. We can add this to stuff the signIn, so separated by a comma, this is called signOut, which I'm going to add as an async function. Once again, we can destructure our commit method and set up the rest of our function and then paste in the contents. Will again be using this action to commit the user's status method and since we are logging out, we want the user to be null. So just after the cut section, we're going to commit the name of our mutation, which is the userStatus, and set the payload to be null. So now we have our signOut action all now setup, we can now dispatch this over in the admin.view. Let's go to our sign up method where we could the contents out before. Inside here we're going to access the star which will import in just a moment. We can call dispatch. On the name of the action we want to dispatch is signOut. We can then replace our firebase impulse just above with our store and the file path is../. We can access the store folder and then the store file. Save this under to the projects. We don't see any detail, so let's login. Scroll up and we have the logged in user email, click on "Sign Out." We now see these moves the user email from the screen. So our sign up method is now still a work in, but this time it's placed into our central store. We're making good progress with Vue X and also our project. Vue X can seem a little confusing at first. It is just something which becomes more clearer with practice. You've already seen most of the core concepts of Vue X. So there is not that much extra to learn. Lot of what we cover for the rest of this section is focused on simplifying our code and making it more organized. 45. Mapping getters: We now know how to use getters to access state from our stall. We then add these getters as computed properties just like here inside of the admin components, to allow us to keep them updated if the state changes. This works completely fine, but there is a way we can simplify this code, which will be useful if we have a lot more getters which you want to setup. We can do this by using mapGetters, which is a helper provided by Vuex. To use this we first need to import this from our Vuex library. Up at the top of our scripts, we can import as a named import mapGetters, which is from the vuex module so we don't need the file path. We can then add mapGetters to our computed properties objects. Inside here we can use the three dots, which is the ES6 spread operator, which allows us to mix these getters in with any existing computer properties which you may already have. MapGetters takes in an array in which we add the names of the getters which you want to use. The getters which you want to use are simply listed below. We have; get menu items which were add in as a string separated by a comma, we also have number of orders and the third one is the current user. Now we can delete the existing computed properties. Give this to save and go over to the browser. We can test if this is working okay. Let's scroll down to our menu. We have the menu items, so get menu items is still working. We can test the current user is working too by login in. Scroll up and we see the e-mail just there, meaning everything is now working fine. Not so long ago we used to get an error message when using the spread operator and we needed to add an additional Babel plugin. This is now no longer the case with the latest version of the Vue CLI. To finish this off now we can go back over to Visual Studio Code, and repeat this over in the menu components. We can import the helper from Vuex at the top of our script, which was mapGetters from vuex and scroll down to our compute its action. We could remove get menu items, and replace this with mapGetters. Remember this takes in an array and the string name was get menu items. We can also add more getters in the future if we like, but for now let's save this and go over to the menu. Click on the menu link, and our menu now still works. If like me, you were currently seen an empty array inside of the baskets, when it is empty, we can also remove this code from earlier. If you go over to the menu.view, we can scroll up to our template, and am not going to remove this from just below our basket text where I'll put it. state. orders. I should remove this, and our basket is now updated. Using the mapGetters helper it's a useful way to organize our code and the benefits become even bigger as we add more getters to our application. 46. Splitting our store into separate files: Having all of our states, both from the application and from external sources, such as Firebase inside of our one central store can be convenient. Also, as you would expect, it can get pretty crowded as our application grows with all of the actions, mutations and the getters in one place. Luckily, Vuex does not restrict the way we structure our store. We can split it up into multiple files to make our code more organized and maintainable. In this video and also the next, I'm going to show you a few different ways to organize your store and also how to use modules. Of course, you may also come up with your own preferred way too. The first way I'm going to cover is the split our actions, getters and mutations into their own separate files. These three new files will also live in the store folder. Let's go over to our store inside of the sidebar. And we can create a new file for each one of these. The first ones is actions.js, the next one is for the getters.js, and the third one is for the mutations. I'm going to start by quoting our actions from the main store.js file, and then pasting them inside of our new actions file. So inside here, let's look for our actions and we can remove everything inside of the surrounding curly brace. I'll sign out and also sign in, leaving just the curly braces surrounding this. Take these out, and then head over to the actions.js. We can paste these in, and we also need to export these as a constant. So we can import these inside of our main store. So the first one of sign-in, we can export this as a constant. Since it's now no longer part of the method's object, we also need to turn this into a standalone function. We can add an equals after the function name. We can repeat this also for the sign out just below. So export const, replace the colon with the equals. We also need to import our firebaseAuth too, up at the top. This is a name export. So firebaseAuth and this is from the file path of dot-dot slash and then firebase. If we scroll down, since these also now standalone functions, we just need to remove the comma separating the sign-in and sign out. We can do exactly the same if you have more actions, and we will add more actions in this project later on. For now though, we need to import this back into our store.js, where we just remove these from. Let's begin up at the top. We can remove our imports from firebase, and instead we could replace this with a star, which we use to import the entire contents of our new file rather than a single member. This will import all of our actions from our actions file. This name of actions is up to us, but this is simply the name we use to refer to the imports object. Some actions make sense. This is in the same folder, so simply dot slash and then actions. We can then go down to the bottom of the file where we have our actions object. We can remove the colon and the curly braces, leaving a reference to the actions which we just imported. We can now test this action is still working by logging in and out. So we still see the user's e-mail in the admin. Let's head over to forward slash admin, scroll down to the bottom, sign-in. Hit the "Sign in" button. Then if we scroll up to the top, we see the signed in user's e-mail. Click "Sign out" and both file functions now still seem to working. So we just need to do exactly the same for our getters and mutations. This is definitely a challenge I think you can do by yourself. Just follow the same process, moving the mutations and the getters to their own file, just as we have done with the actions. So pause the video and give it a go if you feel confident doing so. I'm going to begin over in the getters. Head over to the store.js. We can grab all three of our getters, over to our new file, paste these in, export const, all three. Remember, since these are now standalone functions, we need to replace the colon with an equals, since these are no longer part of an object. We also need to remove the commas separating each one and then we can import these back into our store.js. Just like before we can remove the object pointing to a getters reference, which we can now import at the very top, replace the getters, and then the same for the mutations. Here we have the addOrder and the userStatus. Let's remove both these. We can also remove an object while we're here into the new mutations file. Let's add these in, export const, add the equals. Also the same for the second one, add the equals in and also remove the comma. If you still have any commented code, we can also remove this. This is no longer needed. Back over to our store. We can import this. This was the mutations. Also change the file path too. So this it. Now gives this a "Save" and go over to the projects. Everything still works as normal. Let's try out the admin. Everything looks fine. So this is just one way to structure our Vuex code. Well, you can already see how this could benefit us as the application grows. Next, we're going to cover modules, which is another useful way to organize the code inside of our Vuex Store. 47. Using modules: Vuex also allows us to organize our code into modules. We discovered separating our actions, getters, our mutations into the own files, which was an improvement. But we can improve things even further by grouping together related functionality. For example, everything which is currently in our store can be divided up into three groups. It's even related to our menu, the orders, or our users. So we can organize our code into these free modules. I'm going to do this over in the style folder. Inside here we can create a modules folder, to store our free new files. This also going to be JavaScript files. So the first one is for the menu functionality. Still inside the modules wE creates the orders.js, and finally the users. Make sure that these all nested inside of the new modules folder and then we can start with our menu. Inside of here we can add all of the state getters, mutations, and actions which are related to our menu and store these inside of a constant. So we can set up the state as an objects. We can do our getters, the mutations. Then finally, the actions. I'm going to begin in this file by adding our menu items from states, which we currently have a nice tall.js. Inside here, the state has our menu items, which is an object. Let's locate the closing curly brace. I'm to move everything inside here. Leaving the orders are and also the current user. Paste these in it to our menu.js inside of our states objects. There were two pieces of state in our store are related to the orders and the user. So on add these to the own module soon. Next up I'm going to grab the get menu items, which is a getter from our guesses.js file. Let's cut this line again. Over two are related to the over two modules. We can just grab the first one. Go down to the getters is face this in. This function is also now on our getters object two. We need to return this back to a method by changing equals to a colon. Comma can also remove the x-box. We don't have any mutations to add, and we'll add some actions to this file later on. When x needs to export all of these constants, so we can use them in our files. We have our states, we have our getters, mutations, and actions. So we can't export default, an object which will contain these four variables. So state, mutations, getters, and finally, the actions. Like in the last video, I would encourage you to complete the orders on the user's modules by itself. It does matter if you mess things up. I'm going to go ahead until this now. We can always compare the code at the end. Remember two for each functional copy over into our modules, we need to replace the equals with a colon, just as we have looked at here. Let's now move on to the orders. This new module. We can create a constant of states. We can create our mutations, the getters, the actions, and then finally export defaults of objects for these four variables. Wireless is empty, just changed this. I'm going to select all and copy and paste this over inside of the users.js. Then we can begin to work with our orders. First of all, inside of the states, we can grab any state which related to orders from the store.js. Our orders are initialized as an empty array. Let's remove this, this is interstates. We have mutations or mutations folder, which is our add to order. Remove this base is same, remember to remove the exports and also set this back to be a colon. We also have a getter, which is the number of orders. Remove this and paste this in to our module. We don't currently have any actions. So for now we can save this file and also the getters. We can begin to work on the users.js module. The very top for the state we have the current user which you can grab from our stall, which is currently set to know. We can add this end next step for the mutations, we have the user status. The mutations.js, grab all of the contents and paste this in to a wall object, remove our export, setup, our colon, and down to our getters. There is one getters we need for this file, and this is to get the current user from our getters.js file. Let's remove this, remove our exports and the colon, and down to the actions for the actions related to the user, we have the sign-in method. Let's grab this from our actions.js. We can also grab the sign out while here too. Let's grab both of these phases in it. So I'll uses module as ever. We can remove the exports at a colon. We will also need to separate these two with a comma. The same design in, this action also uses the firebase off. We need to grab this also from our actions file and add this into our users module. Make sure all of our files are now saved. I know Thom Mayne store.js file. We now need to import our free new modules. We can also remove our getters, mutations, and actions. I'm going to import our many module from the file path of./ into the modules folder and the menu. That's our decision to more times. This one is for the orders, both /orders. Then the last one was for the users, scroll down to our store objects. We can remove our states. In fact, we can remove everything from inside here and then replace these with our modules, which is an object, but we're going to pass in the menu orders and also the users. Also just to clean things up, I'm going to remove our actions, getters, our mutations files. We no longer need these inside of our projects. But you can need these in for reference if you prefer. In fact, it may be better to use them for unrelated state which does not belong in a module of its own. Now let's save this file and head over to our application. How much it's changed the file path. I will use this file, which just means changes to a double../ over to the projects. Let's test the menu items to begin. These all shown on the screen. We can try logging in. The admin out down to the bottom where we can add our email and password. We can still sign in and also sign out. This appears to be all still working, but this time using modules. We will also come back to these modules in the next section and add to them as we learn how to keep the data from a store in sync with Firebase. 48. Binding Vuex to Firebase: I'm going to begin this section by adding Firebase bindings to Vuex. Now that we have Vuex added to our application, we now have one centralized place for all of our data and our state. In this section, we'll also be binding our Vuex door to Firebase. While Vuex may be a convenient central location to push and retrieve our data, it is not a persistent data-store. This means if we reload the app, any changes made to the store are then lost. To fix this and make sure our menu items and orders are stored permanently, I'm going to keep the Vuex store in sync with Firebase. We will do this with a package called Vuexfire, and this package is maintained by the call VJS team, and it will allow our central Vuex store to be kept in sync with our Firebase data. It does this by listening to our Firebase database and then communicating mutations to change our state to match. At the moment, if we go inside of our admin, we can add a new pizza inside here. We can add this, and we can see that this is not added to our menu, or if we go over to the menu components, we don't see it added there either. This is because if we go over to our store modules. So let's go into the menu.js, and then up to our state. Inside here we just have our dummy data. So now will be a good time to remove this and replace this with an empty array. So I'm going to remove all the contents from inside our states, we can leave the name of menu items, but this time I'm going to set this equal to an empty array. This will soon be kept in sync with Firebase. So all the data which we have inside of our database will then be reflected inside the state. Meaning we can still use our get menu items getter to grab our state and push it to our components. So now let's install the package which we need, which is called Vuexfire. I'm going to do this via npm, with the i command on the package name is Vuexfire, and this should just take a few moments to install. Great, with this now, we can verify this is installed inside of the package.json, we can go up-to dependencies and receive Vuexfire is installed here, and the next step is to add our Firebase mutations. It is added to the root store and these in mutations, we need to mutate our state every time the data inside the Firebase changes. So let's go over to the root store.js inside of our stall folder. I'll probably talk, we first need to import these from Vuexfire. This is going to be named import. So inside the curly braces, Vuexfire mutations, on the package is Vuexfire. This will then allow us to inject these mutations into the root of our store. So we can add the mutations with the matching name from above. Now I have this, the next step is to enhance our actions. This takes our normal actions which we have in our store, and then add some additional parameters to bind or unbind our state to a Firebase reference. So in our case, we combined our Firebase menu and oldest collection, and we will look at how to do this now. Let's set this up back in the menu module, first, we need to import the Firebase action, just like we just did with the Firebase mutations at the very top. Okay, this is named export, so we add this inside of the curly braces, the name is Firebase action. Once again, from our Vuexfire package, we're also going to be dealing with our menu reference, so we can also import this from our own Firebase file. It will be called the DB menu ref. The file path is dot, dot slash, dot, dot slash, and the filename of Firebase. So now inside this menu module, we already have our actions objects setup. Inside here we're going to use the firestorm action we just imported, rather than using a regular action. This will wrap our action so we can use Vuexfire to keep our data in sync with Firebase, and I'm going to call this new action set menu ref. We can then access the five-star action, which we just imported, install action also takes in our context objects just as a regular action does, but as we mentioned before, it also enhances it with some new functions to help with binding it to Firebase. Let's set this up as a function. The first thing to do inside of our function body is to return the context and then access one of the extra functions provided called bind fire store ref. But what exactly do we want to bind to Firebase? If we scroll up, we already have inside of this file lead two things which we want to bind. We have a reference to our database which points to our menu collection inside of our states. Just below, we have our local menu items. So these are the two references which you want keep in sync. We combine these together and make sure the data is exactly the same. So first of all, let's pass in our state of menu items. And then the second argument is going to be our db menu ref. If we now go over to our application, which determined with this, this has been automatically added in by the text editor. So this just needs to be viable action, back over to application, you see we've now lost our menu items. This is because we're missing one important thing. We've created our action over in the module, but we've not actually dispatched it. This particular action does not change our state, rather, it binds to Firebase instead. Therefore, we want to dispatch it as soon as the application loads. A good place to do this would be inside of the created hook in the main app.view file. Let's head over to the app.view and down to our script. We can add the created hook just after our components. We dispatch this just as with any action, we can access this dot star dot dispatch. The first thing is passing easy action which is named set menu ref. The second argument is the payload, which is DB menu ref, which points towards menu collection in our database. Now we've included the DB menu ref, we also need to import this at the top of our scripts from our Firebase file, which is located at dot slash, and then Firebase. Suddenly, inside of the created hook, we'll dispatch the action once the app is created. This will make sure our store is bound to Firebase right away. Now hopefully if we save this file and then head over to our project, we now see inside of the menu we have our pepperoni pizza, which is now pulled in from our database. Let's head over to the admin routes. We can check this is being displayed correctly inside here too. We see the pepperoni pizza also in here. Let's try adding one more. We can add this with a default data. Now see the margarita has been pushed to our database and also reflected inside our menu. So this is really good progress and something which is really important for our application. Next up we're also going to do the same with our orders and synchronize these with Firebase. 49. Sync orders with Firebase: While we're on the subject of keeping our menu items in sync with Firebase, we can also do the same with our orders. To begin, I'm going to head over to the Firebase config file, which is a firebase.js. We already have a database reference to our menu. We also need to do the same for our order too. I'm going to duplicate this and changed the dbOrders reference, which we are going to point to our orders collection. Remember, it is okay we don't have an object named orders yet inside the Firebase. The first time we push a new order, it will be created for us. Then we can go over to the app.vue components. Then inside here, we also need to import this reference. We have the menu reference, so we can also grab our new orders reference. Then scrolling down inside of the creative hook, we can duplicate this and do the same for our orders. This is going to keep in sync our orders reference, which will create in just a moment with our reference from Firebase. This set orders reference is an action we have not created, so let's go over and do this now. This is going to be similar to set menu ref, which we created in the last video. Let's copy this from our menu. Menu is inside of the modules. Grab this from the actions and then we can go over to our orders.Js paste this in as an action, and all we need to do is to change any reference from our menu to be orders. The name, the orders ref, this is simply orders, which is the name of our state just above, which is said to be an empty array. Remember, for this to work, we also need to import our Firebase action and our orders reference. We can go up to the top of the file above our states. Let's import first our Firestore action from our package, which is vuexfire. Second of all, we're going to import our dbOrdersRef, which we just created in our Firebase file. so../firebase. Just like with the menu, this is going to add an action, which binds our orders, which is the name of our state inside this module with all our ordersRef, which points to our collection inside of Firebase. With this now in place, we can setup a getter just below, which is going to pull our orders from Firebase. I'm going to call this getOrders. This is going to take in our states inside of our function and then return our state the orders. You may begin to see a pattern here as a lot of what we are doing is just the same as we did for the menu items. We set up a binding between local, state, and Firebase then create a getter to grab this data, which you can use inside of our components. We'll use this getter in the next video to display our orders inside of the admin. 50. Displaying orders in the admin section: We now have our Firebase bindings sets of our orders, where we created our old reference inside of our actions. We also created a getter to pull in our items from state. Let's now use this getter inside the admin component to display the orders and also to change our shopping basket to push new orders to Firebase rather than directly to all view Expo. I'm going to begin by pushing these orders to Firebase inside of the menu dot view components. Down at the very bottom. Inside of all methods we have addNewOrder, which is currently committing a new mutation called addOrder. Inside the orders, this is the addOrder mutation and this is pushing directly to our store. I'm going to now comment this out and in place, I'm going to add a new action down at the bottom, which is instead going to push our new orders Firebase. This action is going to be called addNewOrder, and this is to be responsible for pushing our new orders to Firebase. I'm going to mark this as async, so we can use a weight inside of our code. We can pass in any context and also the order which is going to be the payload passed to this action. We can set up our function with a try and a catch section for any error handling. Taking in the error, and for any errors, we're going to pass in an alert with the string, ''Sorry, there was a problem placing your order, please try again.'' The transaction is going to be fairly simple, all we need to do is access our dbOrderReference, and then call the add method, which is going to push the payload of order. We are going to way this and this is now our action complete. Notice inside of this action we don't commit mutation, since we don't need to update our own store. Instead [inaudible] is going to handle pulling in our data from Firebase, which will then update our local state too much. We can now call this action from our menu components when placing a new order. First of all, I'm going to create a new constants which is going to contain our audit data as an object, we can pass in AP disorder, which is the pizzas which contained inside of our order, which we can grab from this store basket. However, at the moment this would cause us a problem, our shopping basket is a type of array inside of the data property. However, Firebase will expect an object, so we need to convert this basket to be a type of objects by adding the curly braces. Then we can use the three dots, which is the spread operator, and this will merge in the array items into our objects. Also, I'm going to add a createdAt property, which is going to be equal to a new JavaScript date. Which is going to allow us to pull in our orders in date order, we no longer committing a mutation, so I'm going to comment this out. I'm going to now dispatch our new action and go to access these stored directly, solving polities in just a moment, call our dispatch, passing in the name of our action, which is our new order. Then the payload, which is our old object from above. Scroll up. We can now import our stall at the top of our scripts. From the file path of dot slash, I will stall folder, and then I will stall file. Over to the browser, we can now test this by adding a new order, so I'm just going to order some pepperonis place your order. Now, if we go to the Firebase console, gives us a reload, we now see our oldest collection with our pizzas we created before. Let's try one more, two Margherita's, this is now been added inside a Firebase. However, if we go over to the admin components, so forward/admin, scroll down to our orders. We only see the single hard coded value which we added earlier, so we can now remove these hard coded values and make this dynamic. Remember in the order [inaudible] file, we created a get orders getter, which you can pull in our orders. Now, we go to admin dot view and update our components. Inside of the computed section, we already have our getter which we currently mapping. We can add one more, which is get orders. Then in the template we can loop through and display the orders. Let's look for the order section. Inside of the table body, we can add a V for loop. We're going to store each item inside of the auto variable, we going to also record the index in getOrders, we also need to add a dynamic key. To combine this, grab the key value from order dot ID. The first thing we can do is number the individual orders, rather than the hard coded value before. Inside of the double curly braces, we can access our index number, and I'm going to add a value of one. This is because indexes begin at the position zero, we want the first order to be worn, and then so one. Now, we have our individual order, we're now going to create a second V for loop in the following row. This loop is going to be for all of the pizzas inside of the order, we can store these inside of a variable called OrderItem. We're going to loop through our order and grab all of the individual pieces. We can then add a dynamic key for our list, and the key can be OrderItem and crop the ID. We can then use the OrderItem to replace our hard coded values for our pizza. Inside the double curly braces, we can access the OrderItem dot name, we can access the price, the quantity and also the price down at the bottom. I'm also going to remove the currency symbol, since we'll also be adding some formatting it to all prices later, and this will be automatically added in four rows. Save this, and now we can go to the admin components, scroll down and as our two orders which will now pulled in from Firebase. If you can see these orders on your screen, you've successfully pulled in orders from the central store, which is kept in sync with Firebase. At moment we have two owners, but we will have lots more. There is no guarantee that when we save in order or retrieve it from Firebase, it's going to come back in any particular order. Remember from before when we created our orders objects down in addNewOrder, we also added a created our property, which we can now use to pull in our orders from Firebase in neat date order. We can do this over any orders dot JS inside of our action where we set the five store reference. We access our dbOrderReference and see where we can also add the orderBymethod, which is provided by Firebase, passing in a string. The string is going to be the name of the fields which we want to always buy, this is created that. If we now save this and go over to the browser, we still see our two orders of Pepperoni and then our Margherita's, which are in ascending order. If we want to reverses into descending order, we can also pass in a second arguments separated by a comma of the ESC, which is short for descending over to the admin and nice and now reversed. However, I'm going to keep this as ascending order, since it's more practical for our application. But this is a useful feature if you want to reverse order of anything coming in from Firebase. 51. Moving add new pizza to the central store: Inside of this newPizza.view components, we use this inside of the admin to add new items to the menu. At the moment, everything works completely fine and as expected, we directly push a new pizza objects to Firebase, use dbMenuRef, and then over in at the menu.js module, we have an action setup, which is a bindings pull in any new pizzas and then save them to our storel. What we going to do now is just a refactor. We're going to move the functionality of adding a new pizza into our store. Inside of this menu.js, I'm going to set this up as a new action just under setMenuRef. This will keep all of our related functionality together and more organized. First we can create this action which I'm going to call addMenuItem. This is going to be async as in the context. Then as a second argument, we're going to pass in the pizza as the payload, which will pass when we dispatch this action from our components. We can set up the rest of the function, we can add error handling, so we can add try and catch passing in any errors. Then from now, I'm going to add an alert inside of the back ticks, so we can insert a variable of error, create a new pizza, passing in our error as a variable. Inside of the try section, this again is going to be pretty simple just like with the orders which we call our dbMenuReference. Only add method, passing in the pizza as the payload. Hope at the very top, we already importing our menu reference, so this is fine. Now we can head over to the new pizza components where we can now dispatch this action. We first need to impose our store inside VO script. The final path for our store is dot dot slash into the store folder and then our store file, back down to our add method. I'm going to comment this out, access our store and then we can dispatch our action. The first argument is the action name of addMenuItem. Then the second one is the payload of the pizza, which we can access with this.newPizza. All I need to do now is give this a Save and head over to the admin inside the browser. We no longer using dbMenuReference so we can scroll up and also remove this too. Back over to the browser and into the admin. Currently in the database, we just have the pepperoni and margarita. Let's try one more. That's not a vegetarian. I'm just going to consider using the description and the rest of the options. Click "Add". There we go, we have a new vegetarian pizza inside of our menu. We can also check inside of the menu components and this is also being added too. This is just a small refactor but it keeps all functionality together and more organized. 52. Removing items from the database: We've focused so far on adding new pictures and new orders, but now we're going to shift our attention to removing things from the database. If you go over to Visual Studio Code and head over to the admin dot view components, inside the template, we already have some HTML button set up. We have wanted to remove any menu items and below inside of the orders loop. We also have a button to remove any orders. I'm going to begin in the first person, which is to remove any menu items by adding a Click handler for our delete button. Just after the class we can add a click and then set this up to be Remove menu item, which we want to set up as a method just below. This needs to take in the item dot ID, so we know which one to remove from the database. This click handler is going to dispatch an action from our store, which we're going to create very soon. We already have our store imported, so we can now scroll down and add this as a method. Just after sign out, we can add Remove menu item, which takes in the arguments of the ID which you pass to it. We need to dispatch this action which we're going to call Remove menu item by accessing our store dot dispatch. The action name, which we want to call Remove menu item and also the ID as the payload. Over in the menu dot js which is the store module, we can create this action. Just after add menu item, add a comma. We can set this up which was Remove menu item. This is going to be async. We can parse in any context and also the payload which was the ID, sets about function and also our error handling. Try catch, passing in the errors, and we can alert any errors to the user inside of the backticks. Error removing menu item and then passing the variable which is our error. Inside of our training section, inside here we want to await our documents which we can grab from our DB menu ref, and the documents which we want to grab is the ID which is passed as the payload. We can store this inside of a constant which I'm going to call item. For this item, we can call the Firebase delete method, which is going to remove this from the database. Let's give this a try over in the admin section, scroll down to our buttons inside the menu. We can click on one of these. This is now being removed from our database. Let's just double-check. If we go to the menu, we now want to see the margarita and the pepperoni. It is now removed from our database. Our Firebase findings are also keeping this in sync with our local state, meaning our admin and also menu is exactly the same as our database. We can now do the same for removing our orders on admin screen two. Go back to the admin dot view. If we go to our orders loop, inside of our button we can also add a click handler inside here. This click handler is going to be Remove order. This also needs to take in the ID, which we can grab from order dot ID. Scroll down. We can also create a method for this, stuff that remove menu item. This is remove order, taking in the ID. We can then dispatch an action which we're going to create in just a moment, which is going to be called remove order. Passing in the ID as the payload, this time we're going to create this action inside of our orders dot js module. Let's head over to there inside of the store, inside of our actions object that's located at the end of at new order. We can set to Remove order, pretty much just like we did before. This is going to be async. Passing in any context, the ID as the payload. I would try and our cut section for error handling passing in the error and alerting the user. Again inside of the backticks, the text sorry, there was a problem, removing the order, passing in error as our variable. Just like the menu item, we're also going to take advantage of the Firebase delete method. First let's find our documents by awaiting the DB or this ref accessing the individual documents with the payload of the ID. We can store this inside of a constant called order and then call order dot delete. We can now test this out over in the admin. Let's first check how many orders we have. Inside here we have two separate orders, so we can now delete one of these. I delete second one on to the console and refresh. Since we've removed both our orders, we no longer have the orders collection. This is all working fine, meaning all of our remove buttons are now complete. I'm going to leave this video there, and next we can make the admin more secure by hiding it from unauthorized users. 53. Hiding the admin from unauthorised users: We're going to now do some work over in the admin components. Make these admin section look and behave exactly how we want it to. At the moment, even when a user is not logged in, we still have access to the sensitive information such as the menu items, the orders, we can still remove items, and we can add extra pizzas even when not logged in. What we want to do is to add some conditional rendering using v-if. When a user is not logged in, we simply only want to show the login components. When they are logged in, we want to change it around and hide these components, leaving the remainder of the admin section. If we go ahead and sign in, we can see by our e-mail up at the top, that's our admin view components has access to our logged in states. It has access to this because of a getter inside of the Admin.Vue called "currentUser." I'm going to make use of this now to hide and show the contents. Let's go and look to our admin templates and write down at the very bottom. We'll have a login component just here, then everything above this inside of our template is sensitive information, which we only want to display when logged in. To do this, I'm going to wrap everything else in a new section. Everything above the login. Let's scroll up to the very top, just underneath the admin wrapper, we can create a new section, and then add some conditional rendering using v-if. We can check if the current user is not equal to null. Scroll down, we can now close off the rest of the section, just above our login. Now, everything apart from the login section will only show if the user is logged in with the login component itself. We can do the opposite inside of our v-if statements. We can check if the current user is equal to null. If this is true, this means the current user is not logged in, and then we'll render the login components, give this a save, and then head over to the browser. We couldn't logged in. Meaning we see all of the admin section. If we scroll down to the very bottom, our login component is now hidden. Let's try signing out. Now, this removes all of the sensitive admin information, leaving a login form. Let's check if this is also working after we log in. Once again, we see the admin section, and if we go to the bottom, the login component is now removed. Now we have the admin screen correctly displaying, depending on if the user is logged in, or logged out. 54. Calculating the basket total: But moments inside of our menu section, we can successfully add items for shopping baskets. We can also increase and decrease the quantity for each line item. As you can see here, the number is not yet formatted to a currency value, but we will do this in the next video with a filter. At the bottom, we have the text of order total, but we don't have any total price display in just yet. But this is what we're going to do in this video by setting up a computed property, which is going to recalculate our total. Let's head over to our menu dot view components, and now scroll down to our script. Inside of here, seems our basket is currently an array, we can use the map method to leave through all items in the basket, it's probably price and quantity which is going to recalculate our total. Now, we can do this inside of the computed section, just after where we map our getters, and a comma, and I'm going to call this the total. As begin by initializing a variable called the total cost, which we can obtain very soon and so this two add initial value of zero. Then to obtain this, we're going to loop through our basket, so we can access this done basket, then we are going to use the JavaScript map method, passing in the item variable, which is the each item inside of our baskets. Inside here, the way we're going to grab the value, is going to be by accessing the individual item. We need to multiply the quantity for each item by the item dot price. This will give us the total quantity for each line item, so the first one in the loop, at the moment will be the two margheritas. Then we'll have the three margheritas on the next loop. I can store this in our total cost variable, and then add to the value with plus equals. After this, we're then going to return the value of total cost. This is available when we call our computed property. We can now put the value of total, after our order total here inside the double curly braces. Give us a save and head over to the browser. Inside of our menu, we can now add some pizzas. We now see with one of each quantity, the order total is now being updated. Let's try increasing the value. Again, and also deducting an item and this is updated with each additional item. Now our total basket cost is now displaying. In the next video, I'm going to look at how we can add a global filter to the price so it displays in a currency format. 55. Global currency filter: In the last video, we created a total cost to the bottom of our basket, and then outputted this using a computer property. If we add to the basket quantities, you will notice that every now and again we get a lot of decimal places, so we need to add some format in it to this currency. Each line item has a hard-coded currency symbol, but we don't have one for the order total. To fix this, I'm going to use a npm package called accounting-js, which is going to add some currency parsing and formatting to our numbers. It also works well as a vue.js filter. Installing this is simple, we can use the npm i command inside of the terminal. Let's open this up, then use npm i and the package name is accounting-js. While this is running, I'm going to go back to our server and then into the main.js file where we can import this up at the top. We want to import this as accounting and the package name is accounting-js. We can then set this up as a vue filter by accessing the vue instance and then a method name which is called filter. This will set up a global filter so it's available to use in all of our components. Our filter takes in two arguments. The first argument is the name we're going to give to our filter. I'm going to call this currency. Then the second one is going to be a function. A function is going to take in the value which we pass to it. This is going to be the price which we need to format, so the price of each individual pizza on the order total. We then want to return a new value from our counting package. We're then going to access a method which is called format money and format money takes in our value to process. We can also bring this onto its own line by removing the return statements and also the curly braces, just make our code a little shorter, and also make sure this is spelled correctly too, so change this. We mentioned before that this creates a global filter, so we can use it instantly in any of our components. We need to use this over in the menu of vue components. We can start inside of our order total. To use our filter, all we need to do inside the double curly braces, is to use the pipe symbol and then pass in our filter name, which was currency. This doesn't have a hard-coded dollar symbol, but this is added in from our currency package. Just above, we have the individual price for each line. We can remove the hard-coded dollar symbol, then also add in our currency filter. We also have one more if we save this and go back to our menu. We also have the prices for each individual pizza. Let's scroll up into our menu section. The option.price, add in the pipe and our currency filter, remove any hard-coded dollar symbol, give this File a Save and over to the browser. Inside of our menu we still see the currency symbol even though we've removed the hard-coded value. Let's add some items to our basket. We see the dollar symbols inside of here too, and let's try increasing the value. The currency now seems to be correctly displaying. The last place where we need to add this filter is in the admin components, where we display our orders. Let's do this now. Inside of the admin components, we need to look for our loop, our order items, and then when we output the price, we can add our filter, just as we did before. Over to the browser and we can test this out. Let's start by placing a new order. Send is off and head over to our admin where we may also need to log in. Add in the user details. Scroll down to our orders, and now we have some formatting for our price. We also have a mistake here for our size, so we just need change this to be orderItem.size, and there we go. This is now our filter all working with the currency format in. Dollar symbol is the default when using accounting-js. This can be easily changed, however, if you prefer, and then add some simple to follow steps if you head over to the documentation. For now though, I will see you in the next video where we're going to add some final touches to our project. 56. Finishing touches: We've done a lot of work to get to this stage of the project, so well done for making it this far. I just wanted to add a few finishing touches in this video, starting inside of the login components. At the moment, if we log out, it may be obvious to some that this is a login section, but we can also add some text to tell the user they need to login. Over any login view components, let's head over to the top of the templates. We will find our form and also our login wrapper. Inside here, I'm going to add a "p" elements with some text. Please login to continue. Save this and back over to the browser. We'll now see our text on here, instruct new user to login. The next thing I'm going to do is to add a navigation guard to this admin. If the user is logged in, remember, we can see sensitive information and anybody who has access can see the orders and also remove any orders or pizzas. To protect this admin if the user were to navigate away without logging out, we can add a navigation guard, which is going to alert the user and also log out automatically. Lets do this in the admin.view components. We can add our navigation guard inside of our scripts. Just after our methods, I'm going to add the guard all beforeRouteLeave. As we looked at earlier, this takes in two from and also next. The first thing we want to do is add an if statement where we can add a confirm box. This will alert the user that they will be logged out if they continue to navigate away from the admin area, so we can have a string of "You will be logged out when leaving admin." This is a question. If this is true, if they continue to navigate away, what I'm going to access our store, we can then call dispatch and the name of the action we want to dispatch is sign out. This will automatically log the user out when leaving the admin. If they were to cancel this conformation, we can add this in an else statements. All we want to do inside here is to stay on the same routes. We could do this by passing false to next. Let's say this under to the admin, we need to log in. Now, we're inside the admin components. Let's try and go over to the menu. We get an alert. If we cancel this, we stay on the same page. Back to the menu. Click on "Okay". You see we logged out but we still on the admin page. To continue on to the menu components or any over's, then you also need called next inside here. We can try this once more. We're now logged in. Let's try the about. We can cancel and we're still inside the admin. Let's try once more on okay and we now take into our over routes. The final thing is some minor CSS, which I'm going to add to the main view down in the Style section. The first one I'm going to do is to target our inputs and our text area for our new Pizzas input, so input, textarea. All I'm going to do here is to increase the font size to be 1.1 rems. Next, we want to add some general style into the buttons so we can't remove the border by setting to null and also increase the font size to be 1.1 rems too. Inside of our app, we also have some classes of btn_green and also btn_red. This also currently missing our styles. Let's start with green. All you need to do is to set the background color and set is to be an rgb value of 101,168, and then 101. Next, the btn_red. The background color, this is also going to be an rgb value of 241, 70, and also 70 giving us the red color. Over to the browser, we have green colors inside here and also here too. Let's try the admin section, where we also have our red buttons. We have the red sign outs. Also, where we remove the orders on pizzas, we have our red buttons too. If we wanted to, we could go even further with the style in, but I'm going to lead this project here since this is a view JS Course. Next, we're going to move on to a new section which you can cover a new topic, which will be lazy loading and how to split our app into smaller bundles. 57. What is code splitting and lazy loading?: Before we dive into code splitting and lazy loading, first, let's take a quick look at why we may need it. The first thing to note is that the Vue CLI uses web park behind the scenes. It abstracts away all of the configuration so we can focus on developments or the versions of the Vue CLI, you stand a web pack config file available to those in our project directory which we could inspect and modify. This new version we are using in this course does not have it available but we can still see the contents of this file by using the output command from the Vue CLI. We can do this if we go down to the terminal and let's open up a new tab to keep the server running and the command we can use is view inspect. The greater than arrow. The file we want to select is the output JS. It enter and this will generate an output JS file follows inside of our project. Once It's being generated, we can go into our sidebar and into our project. Here's our output.js file, which we just generated. Now if we scroll up and down through the file, there is a lot going on here but we can use the text editors search facility with command or control F. I don't want to search for entry. Entry will take us to near the bottom of the file and point to the main entry point of our application which is located in the main.js file. This file is the top level of our application and contains everything for all projects. Web pack them bundles together everything inside of these projects include all files, all of our assets and then I'll put some into one single file. Which is called the build.js. We can also see this output location by the union of research for outputs and this will point to a file path, which is our project directory. Then it will generate a disk folder follows. Now we know about this input and output. I'm going to remove our output.js file since it is not needed inside our application. This single bundled.js file, which is stored in our disk folder, which we're going to create soon, is downloaded from the server the first time a user visits our website or application. This is completely fine if they build it relatively small. But in some applications which include lots of code and assets, this file can become really big and take a long time to download from the server, particularly on mobile devices. This can lead to a poor user experience. This leads us on to the subject of code splitting. Which is the process of breaking up these bundled file or our application into smaller bundles which we can then only download as in when we need them. We need to decide what is the bare minimum or most important contents which the user needs to initially download to keep the bundle as small as possible. We can then split up the rest of the application to be only downloaded when needed such as any additional menu links which are not commonly used, and only download a nice extra parts when needed. Is what is called lazy loading. If we go into the browser and head over to the homepage of our application. When the user first visits our app, we need to include this homepage because this is the main entry points and also the links at the top so the user can navigate. We do not need to include the components or the contents of these links. However, they could be a separate bundle to only download if a user clicks on them. Another example to save on the initial download size is to download the homepage components, but only the contents to the page fold. The fold is the bottom of the visible browser area so we could only download the content we can see before the user scrolls. Apps such as Twitter, we'll do something very similar by only loading up tweets. As you scroll down the page, which will speed things up. There are also lots more way to split up our code too and the load depends on the design of your application. For example, we may want to exclude the contents of a pop up or even the contents of a section on a page which was rendered by an if statement. As you can see, there are lots of ways to think about and we'll cover some of these in this section. 58. Lazy loading with the Vue router: We can apply code splitting and letter loading when using the view router. This is relatively easy to implement as our pages are already in their own separate files. This means we can separate this page components and only load them when a user visits that link. For example, on the homepage, we may only want to load this home components anything menu, contact, and about us components until a user clicks on them. First, let's go over to the developer tools will right-click and inspect. An incident networked up it reloads and make sure the JavaScript button is clicked so we only see our JavaScript files. Inside here we see our app dot JS file which contains all of our JavaScript for all projects. We can see that if we click on any additional menu links, the normal files are downloaded meaning we currently have all of the applications JavaScript inside of one file. This is important to remember that no other files have been loaded here and this will become more clear very soon. If you want to split up our projects and only load these components inside the menu when a user clicks on them, we need to make a change to our routes dot JS file. We can take advantage of web packs code splitting syntax by using a dynamic import which is a replacement for our original component import slatted over to our route dot JS file inside of the text editor. We are going to save we import our normal components. We're going to replace these with a function which is going to be a dynamic imports, and this function is responsible for importing our components as and when they are called. First of all, let's replace the menu link. I'm going to comment this out, and then setup a function called menu, which is going to use web packs dynamic imports syntax to import the menu from the same file path as above. We copy this as a string, paste this into our import and then we can do exactly the same for our contact and about those links. Comments out the about creates a about function. Where are we going to create an import and the file path is exactly the same as above. Copy this link and paste this in, and then finally we have contact two comment this out. We can do exactly the same create our function and grab our file path for contact. This now means we don't immediately import each components when the application is loaded. Instead, they are now functions and they are only imported when needed by calling this function, this is all taken care of behind the scenes by web pack. Now if we go back over to the browser developer tools, save this file, reload the browser, we can clear our history and then reload. Once again, we see our initial apps because we're on the home components. Let's click on the menu and we'll see a new JavaScript file has been imported with the contents of this components. Let's try the contacts and the about and we'll renew files being generated. These have been loaded on demand from the server, meaning that the code for these three components is no longer in our original apps, meaning we have a smaller bundle size when the app is first loaded. If we click on all of our components again, we see that these files are not duplicated since we've already downloaded them and this is an efficient way to separate our bundle into smaller files and only load them when required. In the next video, we will look at how to use named chunks to group our components together. 59. Grouping components into the same chunk: We now know how to split up the bundle and raise a little components when required. Sometimes though we may want to group together certain related components to be downloaded together, and these groups are called chunks. For example, when a user clicks on any of these links in the menu, we may want to also get all of the other menu components too. This is useful if our menu components is small and we want them to be ready for the user. Let's begin again over in the routes.js file. Currently our menu links, which is the menu about and contact. As we know from the last video, were all imported independently when the user clicks on them. I'm going to now group together the contact and about its components, which is simple to do. All we need to do, inside of our import, is to add a comment of web pack chunk name, and then give this group a name of our choice. So we create a comment with the forward slash and the star. When it closes off with the reverse, which is the star and the forward slash. Inside here, we add the comments of web pack chunk name, all in common case. Then after the colon, we can add a name which you want to provide for our group, and we're going to call this the menu group. We can then grab this group. I'm going to copy this and also add this to our contact. Paste this image to our import, save the file, and then on to the browser. We can reload and clear the console. So again, we see our app.js. If we click on the "Menu", our independent bundle for our menu is loaded in. Now, we should see that the about and contact will be downloaded in the same file. So we have the menu group. Let's try the about. Now, additional pages are downloaded for these two components since they contain in our group. So this is how we can group together related components, and we can really fine tune how we want our page to be loaded for our application. 60. Lazy loading with conditional rendering: Inside of our admin screen, we show and hide certain information from the user, depending on if they are authorized to see it or not. We can also apply lazy loading here too. Which will allow us to only download the hidden sections after the user successfully logs in. I'm going to begin by removing all of the dynamic imports from the routes.js, leaving our network tab more clear for this video. So I'm going to reinstate the original menu. Comment out the dynamic import. The same for About and also for our contact. Adding in all of the original components. So the process of only downloading the content after login is not any more difficult than what we have done so far. It basically involves moving the hidden content into a separate component and then we can use a dynamic import to reintroduce the content back into the admin. We can start by making a new component or a new file called the AdminContent.vue. So let's do this as ever inside of the components folder. So AdminContent. So as ever, we also add our template. We can also create our script tags. Then finally our styles down at the bottom. Now if we go back over to our original Admin.vue. Inside here we're going to begin by moving over some content, to our new components. The content we're going to move over is this section. If we leave in the original login components and grab the closing section, and go all the way up to the top of our template. Take this out, leaving our admin_wrapper div and also our login components over to the AdminContent. We paste this now into our new template. Scroll it to the top. We can also remove our If statements. Check if the current user is not equal to null, we'll handle this functionality in just a moment. We also need to go back over to our admin and move over the contents of the script. All of our imports, we can also copy our data, computed, our methods, and all the way down to the closing script tag. Let's close all of this out. Then paste this inside of our adminContent script, which we created before. Moving the export defaults and paste this into our empty script tanks. Since we're now in a different component, we need to change the name of our component. This time we're going to call it the adminContent. Add content onto the end of this. This new vue component is related to the actual content rather than the login. I'm going to remove the login imports and if we scroll down we can also remove the login components. This should now be all of our hidden functionality moved into its own components. All we need to do now is to move over some styles from the Admin.vue. Let's scroll down to our style section. The styles which we need to remove is basically everything after our admin_wrapper. The admin_wrapper is related to this admin component. We need to grab all of the rest of the styles which are related to the content. So put out everything, leaving the admin_wrapper over to the adminContent and we can paste these inside of our style tags. Give this file a save and now we can go back over to the Admin.vue and we can work on the script area. Before we removed the login components and the registration from the AdminContent. These are part of the original Admin.vue, so we can add these back inside of here. Import login from the file path which is./Login. We're also going to be using the computed property of current user inside of this component. We can conditionally render our content. To do this, we also need to import mapGetters which we've used earlier. This is from our vuex package. We can then add in our export defaults. The component name, which was admin. We can then at register our components and the only component which we need is our login, which we just imported, separated by a comma. We then need to add our computed section, which is for our Getters, so we can spread in mapGetters. Inside of our array, the Getter which we need is the current user. So this Admin.vue is going to be a parent component with the content nested inside. This allows us to conditionally render our content, and we can also dynamically import, just like we did with any of our routes earlier in this section. We do this exactly the same as our routes.js. We're going to create a function for our AdminContent and want to set this up as a in-line arrow function, where we add our dynamic imports, which points to our new components of AdminContent. We also need to register this component for it to work too. So just after our login, let's add our AdminContent. Finally, we can add the component to our template just above. Also using the conditional rendering which we removed earlier. So at the top of our login component, let's add in our AdminContent. This is going to use the if, check if the current user is not equal to null. So this is basically doing the opposite of our login component. If the user here is equal to null we're going to render a login component. If the user is logged in, therefore not equal to null. Instead of this, we're going to display the content. So make sure both of these files are saved and head over to the browser into the admin component. So we're not logged in at the moment, meaning we see the Login component so we can add our email and password. Once we log in, we're taken to the content. We can also test for lazy loading. We can open up the console and head into the Network tab. I'm going to sign out and then reload. At the moment we only have the borne dynamic import, which is for our content. Therefore, we only see the app.js file. If we now try to log in. We then see a second bundle has been downloaded from the server, which is for our hidden content. So this kind of thing is a good use case for if we don't expect many admins to be logging into the system, therefore avoiding any unnecessary code to be downloaded for the end user. And this is just another angle to consider when using lazy loading. 61. Firebase rules: We have set up authentication to only allow logged in users to access our admin. But we also want to make sure we have our back end security too. In case somebody bypasses our security. We can do this with Firebase by adding rules. If we head over to our Firebase console, and then up at the top we have the rules tab inside of our database. If we open this up, at the moment, our back end is no secure. We can see here we have a match for all of our documents inside of our database. Then we are allowing read and write privileges to anybody who accesses our site. We can make this more secure by adding in our own custom reals. I'm going to start by removing the inner match to all of our documents, leaving this automatch just here. This automatch with the file path here, basically points to our database entry points. We can then create inside separate rules for our menu and all it's collections if we wish to do so. I'm going to start with the menu collection. The way to do this, we can add match and then a file path to our collection, which is menu. Inside of our menu we've our separate documents. We can install these inside of a variable called the doc ID which is inside of the curly braces. Inside here, we can then set up any separate rules, or we can even combine rules for read, write, update, or delete actions. Inside here I'm going to allow access to right into our database, update in our database, and also delete inside of the same rule. Inside here we only want to allow users to write, update and delete entries from a database if they are currently registered. We can do this by checking if request dot auth dot uid is not equal to null. Here we are basically checking if the request object, which is provided when we make a request to Firebase, has a unique identifier for the current user. If it does, we then allow them to perform actions on our database, meaning they are registered and authorized to do so. If not Firebase will land at block this request. After this, we also going to allow the read rules. This is because we want to allow all users to read the items from the menu. We can then add some rules for our oldest too. Just below this, we can then create a second march. This time we want to point to our oldest collection. We can again use the document ID, which is a variable used to access any of the individual orders inside of this collection. Begin inside of here with the read rules. Since this is the orders and the orders is only available inside of the admin. We want to only allow users to read our orders if they're logged in. As both we can access the request dot auth objects, we can check if the user has a unique ID not equal to null. Therefore, they are registered and logged in. Then they can read the orders. Next step, we're going to allow the write rules. This is going to be for anybody. Since we want to allow any user to go into all site and creates an order without the need register. Orders are a little more complex in this kind of projects. Here we just write in some basic rules. But we could go a lot further by allowing only the creator of an order to obtain, for example. What this means we would need to extend our project to include the user ID inside of our order. But this is definitely is something which you go ahead and do as a challenge, if you would like to add this to the project. It is now in place, we can hit publish to make these changes live. Now in the next video, we'll move on to building our application for production. 62. Deploying to Netlify: The first step towards deploying our application to the web is to build our project for production. Remember, in the last section we inspected our web pack config file and we looked at how our bundle is output into a new folder called disc. We can create this bundle for production by using the build command, which we can see if we go to the package.jason. Currently for development we are being using the subscripts. But now we can go on to move in our build scripts inside of the terminal. Let's go down to the bottom, and inside the terminal we're going to close down our server with Command or Control C. We can then run npm run build, It give us a few moments to build our application for production. It will also create a new disk folder and once this is done, I will come back and see you in just a moment. Once this is finished inside of the sidebar, when I'll have the disc folder, which will contain a production ready version of our app, containing all of our CSS, all of our assets such as images, and also our JavaScript. These files are minified and optimized for production, along with removing things such as any error messages and warning to siege during developments. We can now take this folder and use it to deploy to Netlify. If you head on to netlify.com, there are lots of hosting providers out there, but this is a really popular and easy to use one, which will get us going in just a few minutes. It also has a free option that you used to. We can quickly get our site online using a Netlify CLI, which will give us a set of commands to push our application to production. If we go back over to the terminal inside of Visual Studio Code, we can install this via npm. We're going to be installing this globally, so if you are on a Mac, you may need to use the pseudo keyword as a prefix. If you're Windows, this won't be necessary, all we need to do is to install the Netlify-CLI with the dash g flag to make this global. I already have this installed, so I'm not going to go ahead and do this. But if you don't, go ahead and run this command and then give it a few moments to install. Once this has been installed, the first command we need to run is Netlify deploy. This may also open up in the browser where you may need to log in or create an account if you don't already have one. Once you've signed up and verify your e-mail address, you'll then be taken to the account area where you can create a new project. You don't need to do this inside the browser since we are going to be doing it here inside of the terminal. You may also be asked to authorize the Netlify CLI 2 on the first use. I'm already logged in it since I've used these many times before. Back over to the terminal, we need to answer a few simple questions and we're ready to go. The first thing we need to do is to use the arrow keys on our keyboard to go down to create and configure a new site. I only have one team name, so I'm going to select this. We can also enter a optional site name. I'm going to leave this empty and allow Netlify to generate a random name. Hit Enter. Next we need to tell Netlify where our build folder is located in our projects and this is simply disc. Before we make this website available for the rest of the world to see, Netlify gives us a draft URL, which we can use to basically test our site, see if everything is working okay first. I want to copy this and open a server inside of the browser. On first glance, everything seems to work okay, we have the homepage, we have the menu, we have our contact and also our about links below. However, if we type out anything else on the end of our URL, if this is false slash admin or any other routes, it will not work. This is because we don't have any pages, we don't have a full search admin route to make a request and get from the server. Since we rely on the router to switch between our pages are components, the solution to this one using a single page application is to tell the server we always want to return the homepage regardless of any URL which is entered in the navigation bar. This means we always get the homepage back and we can then use the router on the front-end to switch between pages. This is pretty simple to do. If we go back to the text editor, we simply add a underscore redirect file inside of our disc directory. Open up our disc and inside the route we can create a new file, which is underscore redirect. Then all we need to do is to type a simple line of code where a forward slash and a star. We then need to tell Netlify to only always return the index.html in all cases with a server status code of 200. So give us a save. Now if we go back to the terminal, we can again run, Netlify deploy. The path once again is the disc folder. We can grab our draft URL. Copy these, paste it in, all the regular links are fine. This time we can type in the forward slash admin route. I will now say this is working. We can just double-check by logging in. This is also working with our database too. We can see our current menu items and also the orders. Once we are happy that everything is working fine and we can finally deploy our application. We can do this simply with a new command. For the final time we're going to run Netlify deploy, but this time we're going to add dash, dash prod on the end for production. Meaning we now happy with our test sides and want to build this for our production. The deploy path once again is disc, give us a few seconds to build our sites. We should now see the message of deploy is live with a live URL, which we can now grab and open up inside of the browser. If you reach to this far, congratulations, this is now your website, deploy it to production. You also have a live link which you can share with others too. 63. Follow me on Skillshare!: A huge congratulations from me for reaching the end of this class. I hope you really enjoyed it and gained some knowledge from it. If you've enjoyed this class, make sure you check out the rest of my classes here on Skillshare, and also follow me for any updates and also to be informed of any new classes as they become available. Thank you once again, good luck, and hopefully, I'll see you again in a future class.