{"id":3482,"date":"2019-01-31T08:44:04","date_gmt":"2019-01-31T08:44:04","guid":{"rendered":"http:\/\/myprojects.advchaweb.com\/?p=3482"},"modified":"2019-02-02T14:37:31","modified_gmt":"2019-02-02T14:37:31","slug":"create-laravel-store-with-vue","status":"publish","type":"post","link":"https:\/\/myprojects.advchaweb.com\/index.php\/2019\/01\/31\/create-laravel-store-with-vue\/","title":{"rendered":"Create Laravel Store with Vue"},"content":{"rendered":"<p>Ref: https:\/\/blog.pusher.com\/ecommerce-laravel-vue-part-1\/<\/p>\n<p>In this article, we will cover how you can use Laravel to build a simple e-commerce application. After this tutorial, you should know how to use Laravel and Vue to make a web application and understand the basics of making an online store.<\/p>\n<p>With the advent of the internet, many regular things became faster and easier. One of the things that improved is commerce. Commercial activities carried out on the web are known as e-commerce.<\/p>\n<p>E-commerce applications make sales of goods and services over the internet possible. If you use the internet often, chances are you have come across one or even used one at some point.<\/p>\n<p>Introduction<br \/>\nAs we mentioned earlier, an e-commerce application makes selling goods and services online very convenient. It provides a listing of the products the seller wishes to sell showing their prices, then a page where you can see all the details of the single product selected, and finally, where to pay for the product and set how you wish to receive it.<\/p>\n<p>With this in mind, we know that to have a useful e-commerce application, we\u2019d need to develop the following:<\/p>\n<p>A listing page to view all our products.<br \/>\nA single page to view product information.<br \/>\nA checkout page where the buyer can enter a delivery address and pay.<br \/>\nA simple dashboard for a buyer to see all purchased products, and know if they have shipped.<br \/>\nA way for the seller to add products to sell.<br \/>\nA way for the seller to see which orders users placed.<br \/>\nA way for the seller to show a product has been shipped to the user.<br \/>\nA way for the seller to see and update all product information.<br \/>\nPlanning the structure of the application<br \/>\nFrom our breakdown above, you may see that this application will have two user types:<\/p>\n<p>Administrator\u00a0\u2013 The owner of the store.<br \/>\nBuyer\u00a0\u2013 The person who wants to buy a gift for a friend.<br \/>\nYou definitely know that the application will also have products that need to be stored. These products will be ordered and you need a way to store and track those orders. These would form the basis of any e-commerce platform.<\/p>\n<p>The basic details we need to store in the different parts:<\/p>\n<pre class=\"lang:default decode:true \">Table\tFields\r\nUser\tname, email, password, is_admin\r\nProduct\tname, description, price, units, image\r\nOrder\tproduct, user, quantity, address, is_delivered<\/pre>\n<p>The basic operations we need the app to carry out, and where these are handled, are:<\/p>\n<pre class=\"lang:default decode:true\">Operation\t                        Controller\r\nLogin\t                                UserController\r\nRegister\t                        UserController\r\nUser profile\t                        UserController\r\nView all orders by a single user\tUserController\r\nView product listing\t                ProductController\r\nView a single product\t                ProductController\r\nEdit a product\t                        ProductController\r\nAdd a new product\t                ProductController\r\nAdd more units to a product\t        ProductController\r\nRemove a product\t                ProductController\r\nOrder product\t                        OrderController\r\nView all orders\t                        OrderController\r\nView a single order information\t        OrderController\r\nDeliver an order\t                OrderController\r\nDelete an order\t                        OrderController<\/pre>\n<p>If you want to go a little deeper, you can consider adding categories, tags, warehouse items, more user types and many other things. However, we will not be considering them for this guide, but you should definitely try it on your own.<\/p>\n<p>A good way to learn is by practicing. You can exercise your mind by doing the task in the previous paragraph.<br \/>\nCreating the application<br \/>\nWe are going to use the Laravel CLI to make a new Laravel application. To create a new Laravel application, run the following command:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel$ laravel new laravel-store\r\nCrafting application...\r\nLoading composer repositories with package information\r\nInstalling dependencies (including require-dev) from lock file\r\nPackage operations: 86 installs, 0 updates, 0 removals\r\n  - Installing doctrine\/inflector (v1.3.0): Loading from cache\r\n...\r\nPackage manifest generated successfully.\r\nApplication ready! Build something amazing.<\/pre>\n<p>Then you can\u00a0cd\u00a0into the project we just created. The Laravel related commands we run throughout the article needs to be run from the root of the Laravel project.<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel$ cd laravel-store\/\r\nteddy@teddy:~\/Documents\/works\/laravel\/laravel-store$<\/pre>\n<p>Creating the models for the application<br \/>\nModels in Laravel provide a very convenient way to interact with the database. They provide methods for all the basic operations you need to run for your database table.<\/p>\n<p>Let\u2019s make the models that will interact with our database and hold business logic. New Laravel installations come with the\u00a0User\u00a0model out of the box, which can be found in\u00a0app directory so let\u2019s make the other two models:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan make:model Product -mr\r\nModel created successfully.\r\nCreated Migration: 2019_01_31_134200_create_products_table\r\nController created successfully.<\/pre>\n<p>We have added the\u00a0-mr\u00a0flag to the\u00a0make:model\u00a0command so that it will generate the accompanying migration and controller for the model.<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan make:model Order -mr\r\nModel created successfully.\r\nCreated Migration: 2019_01_31_134258_create_orders_table\r\nController created successfully.<\/pre>\n<p>Next open the\u00a0app\/User.php\u00a0file and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true \">    \/\/app\/User.php\r\n\r\n    namespace App;\r\n\r\n    use Illuminate\\Notifications\\Notifiable;\r\n    use Illuminate\\Database\\Eloquent\\SoftDeletes;\r\n    use Illuminate\\Foundation\\Auth\\User as Authenticatable;\r\n\r\n    class User extends Authenticatable\r\n    {\r\n        use Notifiable, SoftDeletes;\r\n\r\n        protected $fillable = [\r\n            'name', 'email', 'password',\r\n        ];\r\n\r\n        protected $hidden = [\r\n            'password', 'remember_token',\r\n        ];\r\n\r\n        public function orders()\r\n        {\r\n            return $this-&gt;hasMany(Order::class);\r\n        }\r\n    }<\/pre>\n<p>We are using\u00a0SoftDeletes\u00a0to allow us to mark a database record as deleted without actually deleting it completely. This is useful if you want to be able to restore the data.<\/p>\n<p>We also have an array \u2013\u00a0$fillable, with the column names we want to mass assign on the users table. Mass assignment happens when we call our\u00a0User\u00a0model statically and pass an array to its\u00a0create\u00a0method.<\/p>\n<p>Open\u00a0app\/Product.php\u00a0file and edit as follows:<\/p>\n<pre class=\"lang:default decode:true \">    \/\/app\/Product.php\r\n    namespace App;\r\n\r\n    use Illuminate\\Database\\Eloquent\\Model;\r\n    use Illuminate\\Database\\Eloquent\\SoftDeletes;\r\n\r\n    class Product extends Model\r\n    {\r\n        use SoftDeletes;\r\n\r\n        protected $fillable = [\r\n            'name', 'price', 'units', 'description', 'image'\r\n        ];\r\n\r\n        public function orders(){\r\n            return $this-&gt;hasMany(Order::class);\r\n        }\r\n    }<\/pre>\n<p>The\u00a0Product\u00a0model is quite similar to the\u00a0User\u00a0model. It has the\u00a0$fillable\u00a0array and also an\u00a0orders\u00a0method for establishing a relationship with orders placed on the application.<\/p>\n<p>Now, open\u00a0app\/Order.php\u00a0file and edit as follows:<\/p>\n<pre class=\"lang:default decode:true \">    \/\/app\/Order.php\r\n    namespace App;\r\n\r\n    use Illuminate\\Database\\Eloquent\\Model;\r\n    use Illuminate\\Database\\Eloquent\\SoftDeletes;\r\n\r\n    class Order extends Model\r\n    {\r\n        use SoftDeletes;\r\n\r\n        protected $fillable = [\r\n            'product_id', 'user_id', 'quantity', 'address' \r\n        ];\r\n\r\n        public function user()\r\n        {\r\n            return $this-&gt;belongsTo(User::class, 'user_id');\r\n        }\r\n\r\n        public function product()\r\n        {\r\n            return $this-&gt;belongsTo(Product::class, 'product_id');\r\n        }\r\n\r\n    }<\/pre>\n<p>The\u00a0Order\u00a0model looks slightly different from the other two but is essentially the same thing. We just established a different kind of relationship \u2013\u00a0belongsTo\u00a0that shows which user made an order or which product was ordered.<\/p>\n<p>Defining the migrations for the application<br \/>\nMigrations are a good way to create and maintain your application\u2019s database. It essentially defines how tables should be created or modified.<\/p>\n<p>Migrations are useful because they help you manage the database tables, columns and keys. You can share migration files instead of raw SQL, and because migration files are run chronologically, they make it easy to work with git, so it\u2019s great for teams.<\/p>\n<p>Open the\u00a0create_users_table\u00a0migrations file in the\u00a0database\/migrations\u00a0directory and replace the content with the following:<\/p>\n<pre class=\"lang:default decode:true \">    \/\/database\/migrations\/2014_10_12_000000_create_users_table.php\r\n\r\n    use Illuminate\\Support\\Facades\\Schema;\r\n    use Illuminate\\Database\\Schema\\Blueprint;\r\n    use Illuminate\\Database\\Migrations\\Migration;\r\n\r\n    class CreateUsersTable extends Migration\r\n    {\r\n        public function up()\r\n        {\r\n            Schema::create('users', function (Blueprint $table) {\r\n                $table-&gt;increments('id');\r\n                $table-&gt;string('name');\r\n                $table-&gt;string('email')-&gt;unique();\r\n                $table-&gt;boolean('is_admin')-&gt;default(false);\r\n                $table-&gt;string('password');\r\n                $table-&gt;rememberToken();\r\n                $table-&gt;timestamps();\r\n                $table-&gt;softDeletes();\r\n            });\r\n        }\r\n\r\n        public function down()\r\n        {\r\n            Schema::dropIfExists('users');\r\n        }\r\n    }<\/pre>\n<p>Laravel is quite readable and you can probably figure out what is going on by reading the code. We defined which columns should exist in the table and their attributes.<\/p>\n<p>There are many methods in the\u00a0Blueprint\u00a0class for migrations. You can\u00a0<a href=\"https:\/\/laravel.com\/docs\/5.6\/migrations\">read more here<\/a>.<\/p>\n<p>Next, open the\u00a0create_products_table\u00a0migrations file in the\u00a0database\/migrations directory and replace the code with the following:<\/p>\n<pre class=\"lang:default decode:true \">\/\/database\/migrations\/2019_01_31_134200_create_products_table.php\r\n\r\nuse Illuminate\\Support\\Facades\\Schema;\r\nuse Illuminate\\Database\\Schema\\Blueprint;\r\nuse Illuminate\\Database\\Migrations\\Migration;\r\n\r\nclass CreateProductsTable extends Migration\r\n{\r\n    \/**\r\n     * Run the migrations.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function up()\r\n    {\r\n        Schema::create('products', function (Blueprint $table) {\r\n            $table-&gt;increments('id');\r\n            $table-&gt;string('name');\r\n            $table-&gt;string('description');\r\n            \/\/$table-&gt;integer('units')-&gt;unsigned()-&gt;default(0);\r\n            $table-&gt;unsignedInteger('units')-&gt;default(0);\r\n            $table-&gt;double('price');\r\n            $table-&gt;string('image');\r\n            $table-&gt;timestamps();\r\n            $table-&gt;softDeletes();\r\n        });\r\n    }\r\n\r\n    \/**\r\n     * Reverse the migrations.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function down()\r\n    {\r\n        Schema::dropIfExists('products');\r\n    }\r\n}\r\n<\/pre>\n<p>Finally, open the\u00a0create_orders_table\u00a0migrations file in the\u00a0database\/migrations directory and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true \">\/\/database\/migrations\/2019_01_31_134258_create_orders_table.php\r\n\r\nuse Illuminate\\Support\\Facades\\Schema;\r\nuse Illuminate\\Database\\Schema\\Blueprint;\r\nuse Illuminate\\Database\\Migrations\\Migration;\r\n\r\nclass CreateOrdersTable extends Migration\r\n{\r\n    \/**\r\n     * Run the migrations.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function up()\r\n    {\r\n        Schema::create('orders', function (Blueprint $table) {\r\n            $table-&gt;increments('id');\r\n            $table-&gt;unsignedInteger('product_id');\r\n            $table-&gt;unsignedInteger('user_id');\r\n            $table-&gt;unsignedInteger('quantity')-&gt;default(1);\r\n            $table-&gt;string('address')-&gt;nullable();\r\n            $table-&gt;boolean('is_delivered')-&gt;default(false);\r\n            $table-&gt;timestamps();\r\n            $table-&gt;softDeletes();\r\n        });\r\n    }\r\n\r\n    \/**\r\n     * Reverse the migrations.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function down()\r\n    {\r\n        Schema::dropIfExists('orders');\r\n    }\r\n}\r\n<\/pre>\n<p>Creating seeders for the application<br \/>\nSeeders are an excellent way to pre-populate our database with dummy data. We are going to use the seeder class to create the user account for our administration.<\/p>\n<p>Create a seeder class by running the command below:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan make:seed UsersTableSeeder\r\nSeeder created successfully.<\/pre>\n<p>Now, open the file\u00a0UserTableSeeder.php\u00a0at the\u00a0database\/seeds\u00a0directory and replace the content with the following:<\/p>\n<pre class=\"lang:default decode:true \">\/\/database\/seeds\/UsersTableSeeder.php\r\n\r\nuse Illuminate\\Database\\Seeder;\r\nuse App\\User;\r\n\r\nclass UsersTableSeeder extends Seeder\r\n{\r\n    \/**\r\n     * Run the database seeds.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function run()\r\n    {\r\n        $user = new User;\r\n        $user-&gt;name = \"Admin\";\r\n        $user-&gt;email = \"admin@admin.com\";\r\n        $user-&gt;password = bcrypt('secret');\r\n        $user-&gt;is_admin = true;\r\n        $user-&gt;save();\r\n    }\r\n}<\/pre>\n<p>The seeder class above will create a new admin user in the database.<\/p>\n<p>Recall that when we defined the\u00a0User\u00a0model, we did not include\u00a0is_admin\u00a0in the fillable column. The reason is that we do not want anyone who tries to spoof our application to create an administrator user. This is why we had to create a user instance here so we can access all the columns from the user table.<br \/>\nMake another seeder class for our products table:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan make:seed ProductsTableSeeder\r\nSeeder created successfully.\r\n<\/pre>\n<p>Open the\u00a0database\/seeds\/ProductTableSeeder.php\u00a0file and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true \">\/\/database\/seeds\/ProductsTableSeeder.php\r\n\r\nuse Illuminate\\Database\\Seeder;\r\n\r\nclass ProductsTableSeeder extends Seeder\r\n{\r\n    \/**\r\n     * Run the database seeds.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function run()\r\n    {\r\n        $products = [\r\n            [\r\n                'name' =&gt; \"MEN'S BETTER THAN NAKED &amp; JACKET\",\r\n                'description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua consequat.',\r\n                'units' =&gt; 21,\r\n                'price' =&gt; 200.10,\r\n                'image' =&gt; 'http:\/\/images.thenorthface.com\/is\/image\/TheNorthFace\/236x204_CLR\/mens-better-than-naked-jacket-AVMH_LC9_hero.png',\r\n                'created_at' =&gt; new DateTime,\r\n                'updated_at' =&gt; null,\r\n            ],\r\n            [\r\n                'name' =&gt; \"WOMEN'S BETTER THAN NAKED\u2122 JACKET\",\r\n                'description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua consequat.',\r\n                'units' =&gt; 400,\r\n                'price' =&gt; 1600.21,\r\n                'image' =&gt; 'http:\/\/images.thenorthface.com\/is\/image\/TheNorthFace\/236x204_CLR\/womens-better-than-naked-jacket-AVKL_NN4_hero.png',\r\n                'created_at' =&gt; new DateTime,\r\n                'updated_at' =&gt; null,\r\n            ],\r\n            [\r\n                'name' =&gt; \"WOMEN'S SINGLE-TRACK SHOE\",\r\n                'description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua consequat.',\r\n                'units' =&gt; 37,\r\n                'price' =&gt; 378.00,\r\n                'image' =&gt; 'http:\/\/images.thenorthface.com\/is\/image\/TheNorthFace\/236x204_CLR\/womens-single-track-shoe-ALQF_JM3_hero.png',\r\n                'created_at' =&gt; new DateTime,\r\n                'updated_at' =&gt; null,\r\n            ],\r\n            [\r\n                'name' =&gt; 'Enduro Boa\u00ae Hydration Pack',\r\n                'description' =&gt; 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua consequat.',\r\n                'units' =&gt; 10,\r\n                'price' =&gt; 21.10,\r\n                'image' =&gt; 'http:\/\/images.thenorthface.com\/is\/image\/TheNorthFace\/236x204_CLR\/enduro-boa-hydration-pack-AJQZ_JK3_hero.png',\r\n                'created_at' =&gt; new DateTime,\r\n                'updated_at' =&gt; null,\r\n            ]\r\n        ];\r\n\r\n        DB::table('products')-&gt;insert($products);\r\n    }\r\n}\r\n<\/pre>\n<p>The data we populated the database with is from\u00a0<a href=\"https:\/\/gist.github.com\/dpetersen\/1237910\">here<\/a>\u00a0and is for sample educational purposes. You may require permissions to actually use the images.<br \/>\nWhen you are done making the seeder, you need to edit the\u00a0database\/seeds\/DatabaseSeeder.php, which actually invokes the seeders:<\/p>\n<pre class=\"lang:default decode:true \">\/\/database\/seeds\/DatabaseSeeder.php\r\n\r\nuse Illuminate\\Database\\Seeder;\r\n\r\nclass DatabaseSeeder extends Seeder\r\n{\r\n    \/**\r\n     * Seed the application's database.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function run()\r\n    {\r\n        $this-&gt;call([\r\n            UsersTableSeeder::class,\r\n            ProductsTableSeeder::class,\r\n        ]);\r\n    }\r\n}\r\n<\/pre>\n<p>Now, when we execute the command to seed our database the\u00a0DatabaseSeeder\u00a0class is called and it calls the\u00a0run\u00a0which in turn class the seeder classes we had setup to run.<\/p>\n<p>You can learn more about seeders\u00a0<a href=\"https:\/\/laravel.com\/docs\/5.6\/seeding\">here<\/a>.<br \/>\nCreating the database for our application<br \/>\nWe have defined everything we need our database to have. Now, we need to actually define the database itself. We are going to use\u00a0SQLite\u00a0for this guide, but you can any database you like. You should use a non-file based database like\u00a0MySQL\u00a0if in a production environment (NOTE: I&#8217;m going to use mysql instead).<\/p>\n<p>If you want to use sqlite, Create a database file at\u00a0database\/database.sqlite (NOTE: I&#8217;m going to use mysql instead). Next, open your\u00a0.env\u00a0file and replace the following lines:<\/p>\n<pre class=\"lang:default decode:true \">DB_DATABASE=homestead\r\nDB_USERNAME=username\r\nDB_PASSWORD=password<\/pre>\n<p>with<\/p>\n<pre class=\"lang:default decode:true \">DB_DATABASE=laravel_store\r\nDB_USERNAME=your_db_username\r\nDB_PASSWORD=your_db_password<\/pre>\n<p>That is all for our database setup. Run the migrations to create the database tables for our application and seed it:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan migrate --seed\r\nMigration table created successfully.\r\nMigrating: 2014_10_12_000000_create_users_table\r\nMigrated:  2014_10_12_000000_create_users_table\r\nMigrating: 2014_10_12_100000_create_password_resets_table\r\nMigrated:  2014_10_12_100000_create_password_resets_table\r\nMigrating: 2019_01_31_134200_create_products_table\r\nMigrated:  2019_01_31_134200_create_products_table\r\nMigrating: 2019_01_31_134258_create_orders_table\r\nMigrated:  2019_01_31_134258_create_orders_table\r\nSeeding: UsersTableSeeder\r\nSeeding: ProductsTableSeeder\r\nDatabase seeding completed successfully.<\/pre>\n<p>Defining and securing our endpoints<br \/>\nOur application uses Laravel and Vue to create the best application experience. This means we would need to define APIs to provide our Vue components with data.<\/p>\n<p>Laravel, by default, has support for\u00a0web\u00a0and\u00a0API\u00a0routes. Web routes handle routing for dynamically generated pages accessed from a web browser, while API routes handle requests from clients that need a response in mostly\u00a0JSON\u00a0or\u00a0XML\u00a0format.<\/p>\n<p>Our application will have APIs for most requests. We need to secure our APIs to ensure only authorised users will access it. For this, we will use\u00a0<a href=\"https:\/\/laravel.com\/docs\/5.6\/passport\">Laravel Passport<\/a>.<\/p>\n<p>Install passport<br \/>\nTo install passport, run the following command:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ composer require laravel\/passport\r\nUsing version ^7.1 for laravel\/passport\r\n.\/composer.json has been updated\r\nLoading composer repositories with package information\r\nUpdating dependencies (including require-dev)\r\nPackage operations: 7 installs, 0 updates, 0 removals\r\n  - Installing symfony\/psr-http-message-bridge (v1.1.0): Downloading (connectingDownloading (100%)         \r\n  - Installing phpseclib\/phpseclib (2.0.14): Downloading (100%)         \r\n  - Installing defuse\/php-encryption (v2.2.1): Downloading (100%)         \r\n  - Installing league\/event (2.2.0): Downloading (100%)         \r\n  - Installing league\/oauth2-server (7.3.2): Downloading (100%)         \r\n  - Installing firebase\/php-jwt (v5.0.0): Loading from cache\r\n  - Installing laravel\/passport (v7.1.0): Downloading (100%)         \r\nsymfony\/psr-http-message-bridge suggests installing psr\/http-factory-implementation (To use the PSR-17 factory)\r\nphpseclib\/phpseclib suggests installing ext-libsodium (SSH2\/SFTP can make use of some algorithms provided by the libsodium-php extension.)\r\nphpseclib\/phpseclib suggests installing ext-gmp (Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.)\r\nWriting lock file\r\nGenerating optimized autoload files\r\n&gt; Illuminate\\Foundation\\ComposerScripts::postAutoloadDump\r\n&gt; @php artisan package:discover --ansi\r\nDiscovered Package: beyondcode\/laravel-dump-server\r\nDiscovered Package: fideloper\/proxy\r\nDiscovered Package: laravel\/nexmo-notification-channel\r\nDiscovered Package: laravel\/passport\r\nDiscovered Package: laravel\/slack-notification-channel\r\nDiscovered Package: laravel\/tinker\r\nDiscovered Package: nesbot\/carbon\r\nDiscovered Package: nunomaduro\/collision\r\nPackage manifest generated successfully.<\/pre>\n<p>Laravel Passport comes with it\u2019s own migrations, run the migrations using the following command:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan migrate\r\nMigrating: 2016_06_01_000001_create_oauth_auth_codes_table\r\nMigrated:  2016_06_01_000001_create_oauth_auth_codes_table\r\nMigrating: 2016_06_01_000002_create_oauth_access_tokens_table\r\nMigrated:  2016_06_01_000002_create_oauth_access_tokens_table\r\nMigrating: 2016_06_01_000003_create_oauth_refresh_tokens_table\r\nMigrated:  2016_06_01_000003_create_oauth_refresh_tokens_table\r\nMigrating: 2016_06_01_000004_create_oauth_clients_table\r\nMigrated:  2016_06_01_000004_create_oauth_clients_table\r\nMigrating: 2016_06_01_000005_create_oauth_personal_access_clients_table\r\nMigrated:  2016_06_01_000005_create_oauth_personal_access_clients_table<\/pre>\n<p>Next, run the passport installation command to create the necessary keys for securing your application:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan passport:install\r\nEncryption keys generated successfully.\r\nPersonal access client created successfully.\r\nClient ID: 1\r\nClient secret: 5B2jIrNosAkK2OmnqSKyDNshFjdrYMybEXVsbULe\r\nPassword grant client created successfully.\r\nClient ID: 2\r\nClient secret: OTm1dGfx2leOKISA7eRlLsJdx9DtuXidSqyF3CXS<\/pre>\n<p>The above command will create encryption keys needed to generate secure access tokens plus \u201cpersonal access\u201d and \u201cpassword grant\u201d clients, which will be used to generate access tokens.<\/p>\n<p>After the installation, you need to\u00a0use\u00a0the Laravel Passport\u00a0HasApiToken\u00a0trait in the\u00a0User model. This trait will provide a few helper methods to your model, which allow you to inspect the authenticated user\u2019s token and scopes.<\/p>\n<p>Open the\u00a0app\/User.php\u00a0file and edit as follows:<\/p>\n<pre class=\"lang:default decode:true \">\/\/app\/User.php\r\n\r\nnamespace App;\r\n\r\n...\r\nuse Laravel\\Passport\\HasApiTokens;\r\n\r\nclass User extends Authenticatable\r\n{\r\n    use Notifiable, SoftDeletes, HasApiTokens;\r\n    ...\r\n}<\/pre>\n<p>Next, call the\u00a0Passport::routes\u00a0method within the\u00a0boot\u00a0method of your\u00a0AuthServiceProvider. This method will register the routes necessary to issue the tokens your app will need:<\/p>\n<p>In the\u00a0app\/Providers\/AuthServiceProvider.php\u00a0file update as follows:<\/p>\n<pre class=\"lang:default decode:true \">\/\/app\/Providers\/AuthServiceProvider.php\r\n\r\nnamespace App\\Providers;\r\n\r\n...\r\nuse Laravel\\Passport\\Passport;\r\n\r\nclass AuthServiceProvider extends ServiceProvider\r\n{\r\n    ...\r\n\r\n    \/**\r\n     * Register any authentication \/ authorization services.\r\n     *\r\n     * @return void\r\n     *\/\r\n    public function boot()\r\n    {\r\n        $this-&gt;registerPolicies();\r\n\r\n        Passport::routes();\r\n    }\r\n}\r\n<\/pre>\n<p>Finally, in your\u00a0config\/auth.php\u00a0configuration file, you should set the\u00a0driver\u00a0option of the\u00a0api\u00a0authentication guard to\u00a0passport.<\/p>\n<pre class=\"lang:default decode:true \">     \/\/config\/auth.php\r\n     [...]\r\n\r\n    'guards' =&gt; [\r\n\r\n        [...]\r\n\r\n        'api' =&gt; [\r\n            'driver' =&gt; 'passport',\r\n            'provider' =&gt; 'users',\r\n        ],\r\n    ],\r\n\r\n    [...]<\/pre>\n<p>That\u2019s all for Laravel Passport.<\/p>\n<p>Conclusion<br \/>\nSo far, we have set up our application by defining all the models we need. We have also added migrations for our database, and lastly, we added Laravel Passport for handling authorization for our APIs.<\/p>\n<p>The next thing we will look at is implementing the controllers to handle the different kinds of request we are going to make to the application and the views to interact with the application. Continue to\u00a0part two.<\/p>\n<p>In the\u00a0previous chapter, we set up our application\u2019s migrations and models, and installed Laravel Passport for authentication. We also planned what the application will look like. In this chapter, we will implement the controllers and handle all requests to our application.<\/p>\n<p>Prerequisites<br \/>\nTo continue with this part, please go through the\u00a0first part\u00a0of the series first and make sure you have all the requirements from that part.<\/p>\n<p>Building our controllers<br \/>\nIn the first chapter, we already defined our models and their accompanying controllers. These controllers reside in the\u00a0app\/Http\/Controllers\u00a0directory. The\u00a0User\u00a0model, however, does not have an accompanying controller, so we are going to create that first. Run the following command:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ php artisan make:controller UserController\r\nController created successfully.<\/pre>\n<p>Now, open the created controller file\u00a0app\/Http\/Controllers\/UserController.php\u00a0and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true\">\/\/app\/Http\/Controllers\/UserController.php\r\n\r\nnamespace App\\Http\\Controllers;\r\n\r\nuse Illuminate\\Http\\Request;\r\nuse App\\User;\r\nuse Illuminate\\Support\\Facades\\Auth;\r\nuse Illuminate\\Support\\Facades\\Validator;\r\n\r\nclass UserController extends Controller\r\n{\r\n    public function index()\r\n    {\r\n        return response()-&gt;json(User::with(['orders'])-&gt;get());\r\n    }\r\n\r\n    public function login(Request $request)\r\n    {\r\n        $status = 401;\r\n        $response = ['error' =&gt; 'Unauthorized'];\r\n\r\n        if (Auth::attempt($request-&gt;only(['email', 'password']))) {\r\n            $status = 200;\r\n            $response = [\r\n                'user' =&gt; Auth::user(),\r\n                'token' =&gt; Auth::user()-&gt;createToken('myStore')-&gt;accessToken,\r\n            ];\r\n        }\r\n\r\n        return response()-&gt;json($response, $status);\r\n    }\r\n\r\n    public function register(Request $request)\r\n    {\r\n        $validator = Validator::make($request-&gt;all(), [\r\n            'name' =&gt; 'required|max:50',\r\n            'email' =&gt; 'required|email',\r\n            'password' =&gt; 'required|min:6',\r\n            'c_password' =&gt; 'required|same:password',\r\n        ]);\r\n\r\n        if ($validator-&gt;fails()) {\r\n            return response()-&gt;json(['error' =&gt; $validator-&gt;errors()], 401);\r\n        }\r\n\r\n        $data = $request-&gt;only(['name', 'email', 'password']);\r\n        $data['password'] = bcrypt($data['password']);\r\n\r\n        $user = User::create($data);\r\n        $user-&gt;is_admin = 0;\r\n\r\n        return response()-&gt;json([\r\n            'user' =&gt; $user,\r\n            'token' =&gt; $user-&gt;createToken('myStore')-&gt;accessToken,\r\n        ]);\r\n    }\r\n\r\n    public function show(User $user)\r\n    {\r\n        return response()-&gt;json($user);\r\n    }\r\n\r\n    public function showOrders(User $user)\r\n    {\r\n        return response()-&gt;json($user-&gt;orders()-&gt;with(['product'])-&gt;get());\r\n    }\r\n}\r\n<\/pre>\n<p>Above we defined some class methods:<\/p>\n<p>index()\u00a0\u2013 returns all users with their orders.<br \/>\nlogin()\u00a0\u2013 authenticates a user and generates an access token for that user. The\u00a0createToken\u00a0method is one of the methods Laravel Passport adds to our user model.<br \/>\nregister()\u00a0\u2013 creates a user account, authenticates it and generates an access token for it.<br \/>\nshow()\u00a0\u2013 gets the details of a user and returns them.<br \/>\nshowOrders()\u00a0\u2013 gets all the orders of a user and returns them.<br \/>\nWe used Laravel\u2019s\u00a0<a href=\"https:\/\/laravel.com\/docs\/5.6\/routing#route-model-binding\">Route-Model Binding<\/a>\u00a0to automatically inject our model instance into the controller. The only caveat is that the variable name used for the binding has to be the same as the one defined in the route as well.<\/p>\n<p>Next, open the\u00a0app\/Http\/Controllers\/ProductController.php\u00a0file and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true\">    \/\/app\/Http\/Controllers\/ProductController.php\r\n\r\n    namespace App\\Http\\Controllers;\r\n\r\n    use App\\Product;\r\n    use Illuminate\\Http\\Request;\r\n\r\n    class ProductController extends Controller\r\n    {\r\n        public function index()\r\n        {\r\n            return response()-&gt;json(Product::all(),200);\r\n        }\r\n\r\n        public function store(Request $request)\r\n        {\r\n            $product = Product::create([\r\n                'name' =&gt; $request-&gt;name,\r\n                'description' =&gt; $request-&gt;description,\r\n                'units' =&gt; $request-&gt;units,\r\n                'price' =&gt; $request-&gt;price,\r\n                'image' =&gt; $request-&gt;image\r\n            ]);\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; (bool) $product,\r\n                'data'   =&gt; $product,\r\n                'message' =&gt; $product ? 'Product Created!' : 'Error Creating Product'\r\n            ]);\r\n        }\r\n\r\n        public function show(Product $product)\r\n        {\r\n            return response()-&gt;json($product,200); \r\n        }\r\n\r\n        public function uploadFile(Request $request)\r\n        {\r\n            if($request-&gt;hasFile('image')){\r\n                $name = time().\"_\".$request-&gt;file('image')-&gt;getClientOriginalName();\r\n                $request-&gt;file('image')-&gt;move(public_path('images'), $name);\r\n            }\r\n            return response()-&gt;json(asset(\"images\/$name\"),201);\r\n        }\r\n\r\n        public function update(Request $request, Product $product)\r\n        {\r\n            $status = $product-&gt;update(\r\n                $request-&gt;only(['name', 'description', 'units', 'price', 'image'])\r\n            );\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; $status,\r\n                'message' =&gt; $status ? 'Product Updated!' : 'Error Updating Product'\r\n            ]);\r\n        }\r\n\r\n        public function updateUnits(Request $request, Product $product)\r\n        {\r\n            $product-&gt;units = $product-&gt;units + $request-&gt;get('units');\r\n            $status = $product-&gt;save();\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; $status,\r\n                'message' =&gt; $status ? 'Units Added!' : 'Error Adding Product Units'\r\n            ]);\r\n        }\r\n\r\n        public function destroy(Product $product)\r\n        {\r\n            $status = $product-&gt;delete();\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; $status,\r\n                'message' =&gt; $status ? 'Product Deleted!' : 'Error Deleting Product'\r\n            ]);\r\n        }\r\n    }<\/pre>\n<p>In the\u00a0ProductController\u00a0above we defined seven methods:<\/p>\n<p>index()\u00a0\u2013 fetches and returns all the product records.<br \/>\nstore()\u00a0\u2013 creates a product record.<br \/>\nshow()\u00a0\u2013 fetches and returns a single product.<br \/>\nuploadFile()\u00a0\u2013 uploads the image for a product we created and returns the url for the product.<br \/>\nupdate()\u00a0\u2013 updates the product record.<br \/>\nupdateUnits()\u00a0\u2013 adds new units to a product.<br \/>\ndelete()\u00a0\u2013 deletes a product.<br \/>\nNext, open the\u00a0app\/Http\/Controllers\/OrderController.php\u00a0file and replace the content with the following:<\/p>\n<pre class=\"lang:default decode:true\">    \/\/app\/Http\/Controllers\/OrderController.php\r\n\r\n    namespace App\\Http\\Controllers;\r\n\r\n    use App\\Order;\r\n    use Illuminate\\Support\\Facades\\Auth;\r\n    use Illuminate\\Http\\Request;\r\n\r\n    class OrderController extends Controller\r\n    {\r\n        public function index()\r\n        {\r\n            return response()-&gt;json(Order::with(['product'])-&gt;get(),200);\r\n        }\r\n\r\n        public function deliverOrder(Order $order)\r\n        {\r\n            $order-&gt;is_delivered = true;\r\n            $status = $order-&gt;save();\r\n\r\n            return response()-&gt;json([\r\n                'status'    =&gt; $status,\r\n                'data'      =&gt; $order,\r\n                'message'   =&gt; $status ? 'Order Delivered!' : 'Error Delivering Order'\r\n            ]);\r\n        }\r\n\r\n        public function store(Request $request)\r\n        {\r\n            $order = Order::create([\r\n                'product_id' =&gt; $request-&gt;product_id,\r\n                'user_id' =&gt; Auth::id(),\r\n                'quantity' =&gt; $request-&gt;quantity,\r\n                'address' =&gt; $request-&gt;address\r\n            ]);\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; (bool) $order,\r\n                'data'   =&gt; $order,\r\n                'message' =&gt; $order ? 'Order Created!' : 'Error Creating Order'\r\n            ]);\r\n        }\r\n\r\n        public function show(Order $order)\r\n        {\r\n            return response()-&gt;json($order,200);\r\n        }\r\n\r\n        public function update(Request $request, Order $order)\r\n        {\r\n            $status = $order-&gt;update(\r\n                $request-&gt;only(['quantity'])\r\n            );\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; $status,\r\n                'message' =&gt; $status ? 'Order Updated!' : 'Error Updating Order'\r\n            ]);\r\n        }\r\n\r\n        public function destroy(Order $order)\r\n        {\r\n            $status = $order-&gt;delete();\r\n\r\n            return response()-&gt;json([\r\n                'status' =&gt; $status,\r\n                'message' =&gt; $status ? 'Order Deleted!' : 'Error Deleting Order'\r\n            ]);\r\n        }\r\n    }<\/pre>\n<p>In the\u00a0OrderController\u00a0above we have six methods:<\/p>\n<p>index()\u00a0\u2013 fetches and returns all the orders.<br \/>\ndeliverOrder()\u00a0\u2013 marks an order as delivered.<br \/>\nstore()\u00a0\u2013 creates an order.<br \/>\nshow()\u00a0\u2013 fetches and returns a single order.<br \/>\nupdate()\u00a0\u2013 updates the order.<br \/>\ndestroy()\u00a0\u2013 deletes an order.<br \/>\nThat\u2019s it for our controllers. We have created the controller according to the specifications we laid out in the first part. Next thing we need to do is define our API routes.<\/p>\n<p>Defining our application\u2019s routes<br \/>\nNow that we have fully defined all the requests we would like to make to our application, let\u2019s expose the APIs for making these requests. Open\u00a0routes\/api.php\u00a0file and replace the content with the following:<\/p>\n<pre class=\"lang:default decode:true\">    \/\/routes\/api.php\r\n\r\n    use Illuminate\\Http\\Request;\r\n\r\n    Route::post('login', 'UserController@login');\r\n    Route::post('register', 'UserController@register');\r\n    Route::get('\/products', 'ProductController@index');\r\n    Route::post('\/upload-file', 'ProductController@uploadFile');\r\n    Route::get('\/products\/{product}', 'ProductController@show');\r\n\r\n    Route::group(['middleware' =&gt; 'auth:api'], function(){\r\n        Route::get('\/users','UserController@index');\r\n        Route::get('users\/{user}','UserController@show');\r\n        Route::patch('users\/{user}','UserController@update');\r\n        Route::get('users\/{user}\/orders','UserController@showOrders');\r\n        Route::patch('products\/{product}\/units\/add','ProductController@updateUnits');\r\n        Route::patch('orders\/{order}\/deliver','OrderController@deliverOrder');\r\n        Route::resource('\/orders', 'OrderController');\r\n        Route::resource('\/products', 'ProductController')-&gt;except(['index','show']);\r\n    });<\/pre>\n<p>Putting our route definitions in the\u00a0routes\/api.php\u00a0file will tell Laravel they are API routes so Laravel will prefix the routes with a\u00a0\/api\u00a0in the URL to differentiate them from web-routes.<\/p>\n<p>Adding the\u00a0auth:api\u00a0middleware ensures any calls to the routes in that group must be authenticated.<\/p>\n<p>A thing to note is, using the\u00a0resource\u00a0method on the\u00a0Route\u00a0class helps us create some additional routes under the hood without us having to create them manually. Read\u00a0<a href=\"https:\/\/laravel.com\/docs\/5.6\/controllers#resource-controllers\">about resource controllers and routes here<\/a>.<\/p>\n<p>To see the full route list, run the following command:\u00a0$\u00a0php artisan route:list<\/p>\n<p>Since we will build the front end of this application in Vue, we need to define the\u00a0web\u00a0routes for it. Open the\u00a0routes\/web.php\u00a0file and replace the contents with the following:<\/p>\n<pre class=\"lang:default decode:true \">    \/\/routes\/web.php\r\n\r\n    Route::get('\/{any}', function(){\r\n            return view('landing');\r\n    })-&gt;where('any', '.*');<\/pre>\n<p>This will route every web request to a single entry point, which will be the entry for your Vue application.<\/p>\n<p>Setting up Vue for the frontend<br \/>\nVue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable \u2013\u00a0vuejs.org<br \/>\nLaravel comes with Vue bundled out of the box, so all we need to do to get Vue is to install the node packages. Run the following command:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ npm install\r\n\r\n&gt; webpack-cli@3.2.1 postinstall \/home\/teddy\/Documents\/works\/laravel\/laravel-store\/node_modules\/webpack-cli\r\n&gt; lightercollective\r\n\r\n\r\n     *** Thank you for using webpack-cli! ***\r\n\r\nPlease consider donating to our open collective\r\n     to help us maintain this package.\r\n\r\n  https:\/\/opencollective.com\/webpack\/donate\r\n\r\n                    ***\r\n\r\nnpm notice created a lockfile as package-lock.json. You should commit this file.\r\nnpm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules\/fsevents):\r\nnpm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})\r\n\r\nadded 943 packages from 442 contributors and audited 16939 packages in 14.858s\r\nfound 0 vulnerabilities<\/pre>\n<p>Next, we will need\u00a0VueRouter\u00a0to handle the routing between the different components of our Vue application. To install VueRouter run the command below:<\/p>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ npm i vue-router\r\nnpm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules\/fsevents):\r\nnpm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})\r\n\r\n+ vue-router@3.0.2\r\nadded 1 package from 1 contributor and audited 16940 packages in 5.414s\r\nfound 0 vulnerabilities\r\n\r\n\r\n\r\n   \u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\r\n   \u2502                                                               \u2502\r\n   \u2502       New minor version of npm available! 6.5.0 \u2192 6.7.0       \u2502\r\n   \u2502   Changelog: https:\/\/github.com\/npm\/cli\/releases\/tag\/v6.7.0   \u2502\r\n   \u2502               Run npm install -g npm to update!               \u2502\r\n   \u2502                                                               \u2502\r\n   \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\r\n<\/pre>\n<pre class=\"lang:default decode:true \">teddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ npm i -g npm\r\n\/home\/teddy\/.nvm\/versions\/node\/v8.9.4\/bin\/npm -&gt; \/home\/teddy\/.nvm\/versions\/node\/v8.9.4\/lib\/node_modules\/npm\/bin\/npm-cli.js\r\n\/home\/teddy\/.nvm\/versions\/node\/v8.9.4\/bin\/npx -&gt; \/home\/teddy\/.nvm\/versions\/node\/v8.9.4\/lib\/node_modules\/npm\/bin\/npx-cli.js\r\n+ npm@6.7.0\r\nadded 50 packages from 7 contributors, removed 13 packages and updated 31 packages in 5.253s\r\nteddy@teddy:~\/Documents\/works\/laravel\/laravel-store$ npm --v\r\n6.7.0\r\n<\/pre>\n<p>Next, let\u2019s make the\u00a0landing\u00a0view file, which would mount our Vue application. Create the file\u00a0resources\/views\/landing.blade.php\u00a0and add the following code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;!-- resources\/views\/landing.blade.php --&gt;\r\n&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n    &lt;meta charset=\"utf-8\"&gt;\r\n    &lt;meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"&gt;\r\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\r\n    &lt;meta name=\"csrf-token\" content=\"{{csrf_token()}}\"&gt;\r\n    &lt;title&gt;My Store&lt;\/title&gt;\r\n    &lt;link href=\" {{ mix('css\/app.css') }}\" rel=\"stylesheet\"&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    &lt;div id=\"app\"&gt;\r\n        &lt;app&gt;&lt;\/app&gt;\r\n    &lt;\/div&gt;\r\n    &lt;script src=\"{{ mix('js\/bootstrap.js') }}\"&gt;&lt;\/script&gt;\r\n    &lt;script src=\"{{ mix('js\/app.js') }}\"&gt;&lt;\/script&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>In the code above, we have the HTML for our application. If you look closely, you can see the\u00a0app\u00a0tag. This will be the entry point to our Vue application and where the components will be loaded.<\/p>\n<p>Since we will use\u00a0app.js\u00a0to set up our\u00a0VueRouter, we still need to have\u00a0<a href=\"https:\/\/getbootstrap.com\/\">Bootstrap<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/axios\/axios\">Axios<\/a>\u00a0compiled. The import for Bootstrap and Axios is in the\u00a0bootstrap.js\u00a0file so we need to compile that.<\/p>\n<p>Edit the\u00a0webpack.mix.js\u00a0file so it compiles all assets:<\/p>\n<pre class=\"lang:default decode:true \">    &lt;!-- webpack.mix.js --&gt;\r\n    [...]\r\n\r\n    mix.js('resources\/assets\/js\/app.js', 'public\/js')\r\n       .js('resources\/assets\/js\/bootstrap.js', 'public\/js')\r\n       .sass('resources\/assets\/sass\/app.scss', 'public\/css');<\/pre>\n<p>the\u00a0webpack.mix.js\u00a0file holds the configuration files for\u00a0laravel-mix, which provides a wrapper around Webpack. It lets us take advantage of Webpack\u2019s amazing asset compilation abilities without having to write Webpack configurations by ourselves. You can learn more about Webpack\u00a0<a href=\"https:\/\/webpack.js.org\/\">here<\/a>.<br \/>\nSet up the homepage for the Vue application. Create a new file,\u00a0resources\/js\/components\/Home.vue, and add the following code to the file:<\/p>\n<pre class=\"lang:default decode:true\">&lt;!-- resources\/js\/components\/Home.vue --&gt;\r\n&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;div class=\"container-fluid hero-section d-flex align-content-center justify-content-center flex-wrap ml-auto\"&gt;\r\n            &lt;h2 class=\"title\"&gt;Welcome to My Store&lt;\/h2&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"container\"&gt;\r\n            &lt;div class=\"row\"&gt;\r\n                &lt;div class=\"col-md-12\"&gt;\r\n                    &lt;div class=\"row\"&gt;\r\n                        &lt;div class=\"col-md-4 product-box\" v-for=\"(product,index) in products\" @key=\"index\"&gt;\r\n                            &lt;router-link :to=\"{ path: '\/products\/'+product.id}\"&gt;\r\n                                &lt;img :src=\"product.image\" :alt=\"product.name\"&gt;\r\n                                &lt;h5&gt;&lt;span v-html=\"product.name\"&gt;&lt;\/span&gt;\r\n                                    &lt;span class=\"small-text text-muted float-right\"&gt;$ {{product.price}}&lt;\/span&gt;\r\n                                &lt;\/h5&gt;\r\n                                &lt;button class=\"col-md-4 btn btn-sm btn-primary float-right\"&gt;Buy Now&lt;\/button&gt;\r\n                            &lt;\/router-link&gt;\r\n                        &lt;\/div&gt;\r\n                    &lt;\/div&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            products : []\r\n        }\r\n    },\r\n    mounted() {\r\n        axios.get(\"api\/products\").then(response =&gt; {\r\n            this.products = response.data;\r\n        });\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>The code above within the opening and closing\u00a0template\u00a0tag we have the HTML of our Vue component. In there we loop through the contents of\u00a0products\u00a0and for each product we display the\u00a0image,\u00a0name,\u00a0id,\u00a0price\u00a0and\u00a0units\u00a0available. We use the\u00a0v-html\u00a0attribute to render raw HTML, which makes it easy for us to use special characters in the product name.<\/p>\n<p>In the\u00a0script\u00a0tag, we defined the\u00a0data(), which holds all the variables we can use in our template. We also defined the\u00a0mounted()\u00a0method, which is called after our component is loaded. In this mounted method, we load our products from the API then set the\u00a0products variable so that our template would be updated with API data.<\/p>\n<p>In the same file, append the code below to the bottom:<\/p>\n<pre class=\"lang:default decode:true\">&lt;style scoped&gt;\r\n.small-text {\r\n    font-size: 14px;\r\n}\r\n.product-box {\r\n    border: 1px solid #cccccc;\r\n    padding: 10px 15px;\r\n}\r\n.hero-section {\r\n    height: 30vh;\r\n    background: #ababab;\r\n    align-items: center;\r\n    margin-bottom: 20px;\r\n    margin-top: -20px;\r\n}\r\n.title {\r\n    font-size: 60px;\r\n    color: #ffffff;\r\n}\r\n&lt;\/style&gt;<\/pre>\n<p>In the code above, we have defined the\u00a0style\u00a0to use with the welcome component.<\/p>\n<p>According to the\u00a0<a href=\"https:\/\/vue-loader.vuejs.org\/en\/features\/scoped-css.html\">Vue documentation<\/a>: When a\u00a0&lt;style&gt;\u00a0tag has the\u00a0scoped\u00a0attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in the Shadow DOM. It comes with some caveats but doesn\u2019t require any polyfills.<br \/>\nNext create another file,\u00a0resources\/js\/components\/App.vue. This will be the application container where all other components will be loaded. In this file, add the following code:<\/p>\n<pre class=\"lang:default decode:true\">&lt;!-- resources\/js\/components\/App.vue --&gt;\r\n&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;nav class=\"navbar navbar-expand-md navbar-light navbar-laravel\"&gt;\r\n            &lt;div class=\"container\"&gt;\r\n                &lt;router-link :to=\"{name: 'home'}\" class=\"navbar-brand\"&gt;My Store&lt;\/router-link&gt;\r\n                &lt;button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarSupportedContent\" aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"&gt;\r\n                    &lt;span class=\"navbar-toggler-icon\"&gt;&lt;\/span&gt;\r\n                &lt;\/button&gt;\r\n                &lt;div class=\"collapse navbar-collapse\" id=\"navbarSupportedContent\"&gt;\r\n                    &lt;!-- Left Side Of Navbar --&gt;\r\n                    &lt;ul class=\"navbar-nav mr-auto\"&gt;&lt;\/ul&gt;\r\n                    &lt;!-- Right Side Of Navbar --&gt;\r\n                    &lt;ul class=\"navbar-nav ml-auto\"&gt;\r\n                        &lt;router-link :to=\"{ name: 'login' }\" class=\"nav-link\" v-if=\"!isLoggedIn\"&gt;Login&lt;\/router-link&gt;\r\n                        &lt;router-link :to=\"{ name: 'register' }\" class=\"nav-link\" v-if=\"!isLoggedIn\"&gt;Register&lt;\/router-link&gt;\r\n                        &lt;span v-if=\"isLoggedIn\"&gt;\r\n                            &lt;router-link :to=\"{ name: 'userboard' }\" class=\"nav-link\" v-if=\"user_type == 0\"&gt; Hi, {{name}}&lt;\/router-link&gt;\r\n                            &lt;router-link :to=\"{ name: 'admin' }\" class=\"nav-link\" v-if=\"user_type == 1\"&gt; Hi, {{name}}&lt;\/router-link&gt;\r\n                        &lt;\/span&gt;\r\n                        &lt;li class=\"nav-link\" v-if=\"isLoggedIn\" @click=\"logout\"&gt; Logout&lt;\/li&gt;\r\n                    &lt;\/ul&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/nav&gt;\r\n        &lt;main class=\"py-4\"&gt;\r\n            &lt;router-view @loggedIn=\"change\"&gt;&lt;\/router-view&gt;\r\n        &lt;\/main&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p>In the Vue template above we used some Vue specific tags like\u00a0router-link, which helps us generate links for routing to pages defined in our router. We also have the\u00a0router-view, which is where all the child component pages will be loaded.<\/p>\n<p>Next, below the closing\u00a0template\u00a0tag, add the following code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            name: null,\r\n            user_type: 0,\r\n            isLoggedIn: localStorage.getItem('myStore.jwt') != null\r\n        }\r\n    },\r\n    mounted() {\r\n        this.setDefaults();\r\n    },\r\n    methods : {\r\n        setDefaults() {\r\n            if(this.isLoggedIn){\r\n                let user = JSON.parse(localStorage.getItem('myStore.user'));\r\n                this.name = user.name;\r\n                this.user_type = user.is_admin;\r\n            }\r\n        },\r\n        change() {\r\n            this.isLoggedIn = localStorage.getItem('myStore.jwt') != null;\r\n            this.setDefaults();\r\n        },\r\n        logout() {\r\n            localStorage.removeItem('myStore.jwt');\r\n            localStorage.removeItem('myStore.user');\r\n            this.change();\r\n            this.$router.push('\/');\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>In the script definition we have the\u00a0methods\u00a0property and in there we have three methods defined:<\/p>\n<p>setDefaults()\u00a0\u2013 sets the name of the user when the user is logged in as well as the type of user logged in.<br \/>\nchange()\u2013 checks the current login status anytime it is called and calls the\u00a0setDefaults method.<br \/>\nlogout()\u00a0\u2013 logs the user out of the application and routes the user to the homepage.<br \/>\nIn our\u00a0router-view\u00a0component, we listen for an event\u00a0loggedIn\u00a0which calls the\u00a0change method. This event is fired by our component anytime we log in. It is a way of telling the\u00a0App component to update itself when a user logs in.<\/p>\n<p>Next create the following files in the\u00a0resources\/js\/components\u00a0directory:<\/p>\n<p>Admin.vue<br \/>\nCheckout.vue<br \/>\nConfirmation.vue<br \/>\nLogin.vue<br \/>\nRegister.vue<br \/>\nSingleProduct.vue<br \/>\nUserBoard.vue<br \/>\nThese files would hold all the pages myStore\u00a0would have. They need to be created prior to setting up VueRouter, so that it won\u2019t throw an error.<\/p>\n<p>To set up the routing for our Vue single page app, open your\u00a0resources\/js\/app.js\u00a0file and replace the contents with the following code:<\/p>\n<pre class=\"lang:default decode:true\">\/\/resources\/js\/app.js\r\n...\r\nimport Vue from 'vue'\r\nimport VueRouter from 'vue-router'\r\n\r\nVue.use(VueRouter)\r\n\r\nimport App from '.\/components\/App'\r\nimport Home from '.\/components\/Home'\r\nimport Login from '.\/components\/Login'\r\nimport Register from '.\/components\/Register'\r\nimport SingleProduct from '.\/components\/SingleProduct'\r\nimport Checkout from '.\/components\/Checkout'\r\nimport Confirmation from '.\/components\/Confirmation'\r\nimport UserBoard from '.\/components\/UserBoard'\r\nimport Admin from '.\/components\/Admin'\r\n\r\nconst router = new VueRouter({\r\n    mode: 'history',\r\n    routes: [\r\n        {\r\n            path: '\/',\r\n            name: 'home',\r\n            component: Home\r\n        },\r\n        {\r\n            path: '\/login',\r\n            name: 'login',\r\n            component: Login\r\n        },\r\n        {\r\n            path: '\/register',\r\n            name: 'register',\r\n            component: Register\r\n        },\r\n        {\r\n            path: '\/products\/:id',\r\n            name: 'single-products',\r\n            component: SingleProduct\r\n        },\r\n        {\r\n            path: '\/confirmation',\r\n            name: 'confirmation',\r\n            component: Confirmation\r\n        },\r\n        {\r\n            path: '\/checkout',\r\n            name: 'checkout',\r\n            component: Checkout,\r\n            props: (route) =&gt; ({ pid: route.query.pid })\r\n        },\r\n        {\r\n            path: '\/dashboard',\r\n            name: 'userboard',\r\n            component: UserBoard,\r\n            meta: {\r\n                requiresAuth: true,\r\n                is_user: true\r\n            }\r\n        },\r\n        {\r\n            path: '\/admin\/:page',\r\n            name: 'admin-pages',\r\n            component: Admin,\r\n            meta: {\r\n                requiresAuth: true,\r\n                is_admin: true\r\n            }\r\n        },\r\n        {\r\n            path: '\/admin',\r\n            name: 'admin',\r\n            component: Admin,\r\n            meta: {\r\n                requiresAuth: true,\r\n                is_admin: true\r\n            }\r\n        },\r\n    ],\r\n})\r\n\r\nrouter.beforeEach((to, from, next) =&gt; {\r\n    if (to.matched.some(record =&gt; record.meta.requiresAuth)) {\r\n        if (localStorage.getItem('myStore.jwt') == null) {\r\n            next({\r\n                path: '\/login',\r\n                params: { nextUrl: to.fullPath }\r\n            })\r\n        } else {\r\n            let user = JSON.parse(localStorage.getItem('myStore.user'))\r\n            if (to.matched.some(record =&gt; record.meta.is_admin)) {\r\n                if (user.is_admin == 1) {\r\n                    next()\r\n                }\r\n                else {\r\n                    next({ name: 'userboard' })\r\n                }\r\n            }\r\n            else if (to.matched.some(record =&gt; record.meta.is_user)) {\r\n                if (user.is_admin == 0) {\r\n                    next()\r\n                }\r\n                else {\r\n                    next({ name: 'admin' })\r\n                }\r\n            }\r\n            next()\r\n        }\r\n    } else {\r\n        next()\r\n    }\r\n})\r\n...<\/pre>\n<p>Above, we have imported the\u00a0VueRouter\u00a0and we added it to our Vue application. We defined routes for our application and then registered it to the Vue instance so it is available to all Vue components.<\/p>\n<p>Each of the route objects has a\u00a0name, which we will use to identify and invoke that route. It also has a\u00a0path, which you can visit directly in your browser. Lastly, it has a\u00a0component, which is mounted when you visit the route.<\/p>\n<p>On some routes, we defined\u00a0meta, which contains variables we would like to check when we access the route. In our case, we are checking if the route requires authentication and if it is restricted to administrators or regular users only.<\/p>\n<p>We set up the\u00a0beforeEach\u00a0middleware on the\u00a0router\u00a0that checks each route before going to it. The method takes these variables:<\/p>\n<p>to\u00a0\u2013 the route you want to move to.<br \/>\nfrom\u00a0\u2013 the current route you are moving away from.<br \/>\nnext\u00a0\u2013 the method that finally moves to a defined route. When called without a route passed, it continues the navigation. If given a route, it goes to that route.<br \/>\nWe use\u00a0beforeEach\u00a0to check the routes that require authentication before you can access them. For those routes, we check if the user is authenticated. If the user isn\u2019t, we send them to the login page. If the user is authenticated, we check if the route is restricted to admin users or regular users. We redirect each user to the right place based on which access level they have.<\/p>\n<p>Now add the following lines to the end of the\u00a0app.js\u00a0file<\/p>\n<pre class=\"lang:default decode:true \">    const app = new Vue({\r\n        el: '#app',\r\n        components: { App },\r\n        router,\r\n    });<\/pre>\n<p>This instantiates the Vue application. In this global instance, we mount the\u00a0App\u00a0component only because the\u00a0VueRouter\u00a0needs it to switch between all the other components.<\/p>\n<p>Now, we are ready to start making the other views for our application.<\/p>\n<p>Conclusion<br \/>\nIn this part, we implemented the controller logic that handles all the requests to our application and defined all the routes the application will use. We also set up Vue and VueRouter to prepare our application for building the core frontend.<\/p>\n<p>In the\u00a0next chapter\u00a0of this guide, we are going to build the core frontend of the application and consume the APIs. See you in the next part.<\/p>\n<p>Making the authentication pages<br \/>\nIn the previous part, we created all the view files for our Vue application, although we did not add content to all of them. Let\u2019s start with the login and register pages.<\/p>\n<p>Open the\u00a0resources\/js\/components\/Login.vue\u00a0file and paste in the following code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;!-- resources\/js\/components\/Login.vue --&gt;\r\n&lt;template&gt;\r\n    &lt;div class=\"container\"&gt;\r\n        &lt;div class=\"row justify-content-center\"&gt;\r\n            &lt;div class=\"col-md-8\"&gt;\r\n                &lt;div class=\"card card-default\"&gt;\r\n                    &lt;div class=\"card-header\"&gt;Login&lt;\/div&gt;\r\n                    &lt;div class=\"card-body\"&gt;\r\n                        &lt;form&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"email\" class=\"col-sm-4 col-form-label text-md-right\"&gt;E-Mail Address&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"email\" type=\"email\" class=\"form-control\" v-model=\"email\" required autofocus&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"password\" class=\"col-md-4 col-form-label text-md-right\"&gt;Password&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"password\" type=\"password\" class=\"form-control\" v-model=\"password\" required&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row mb-0\"&gt;\r\n                                &lt;div class=\"col-md-8 offset-md-4\"&gt;\r\n                                    &lt;button type=\"submit\" class=\"btn btn-primary\" @click=\"handleSubmit\"&gt;\r\n                                        Login\r\n                                    &lt;\/button&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                        &lt;\/form&gt;\r\n                    &lt;\/div&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p>Above we have a login form. We don\u2019t have much functionality yet so let\u2019s append the following code to the same file to add some Vue scripting:<\/p>\n<pre class=\"lang:default decode:true \">&lt;script&gt;\r\n    export default {\r\n        data() {\r\n            return {\r\n                email: \"\",\r\n                password: \"\"\r\n            }\r\n        },\r\n        methods: {\r\n            handleSubmit(e) {\r\n                e.preventDefault()\r\n                if (this.password.length &gt; 0) {\r\n                    let email = this.email\r\n                    let password = this.password\r\n\r\n                    axios.post('api\/login', {email, password}).then(response =&gt; {\r\n                        let user = response.data.user\r\n                        let is_admin = user.is_admin\r\n\r\n                        localStorage.setItem('myStore.user', JSON.stringify(user))\r\n                        localStorage.setItem('myStore.jwt', response.data.token)\r\n\r\n                        if (localStorage.getItem('myStore.jwt') != null) {\r\n                            this.$emit('loggedIn')\r\n                            if (this.$route.params.nextUrl != null) {\r\n                                this.$router.push(this.$route.params.nextUrl)\r\n                            } else {\r\n                                this.$router.push((is_admin == 1 ? 'admin' : 'dashboard'))\r\n                            }\r\n                        }\r\n                    });\r\n                }\r\n            }\r\n        }\r\n    }\r\n&lt;\/script&gt;<\/pre>\n<p>Above we have a\u00a0handleSubmit\u00a0method that is fired when the form is submitted. In this method we attempt to authenticate using the API. If the authentication is successful, we save the access token and user data in\u00a0localStorage\u00a0so we can access them across our app.<\/p>\n<p>We also emit a\u00a0loggedIn\u00a0event so the parent component can update as well. Lastly, we check if the user was sent to the login page from another page, then send the user to that page. If the user came to login directly, we check the user type and redirect the user appropriately.<\/p>\n<p>Next, open the\u00a0resources\/js\/components\/Register.vue\u00a0file and paste in the following:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div class=\"container\"&gt;\r\n        &lt;div class=\"row justify-content-center\"&gt;\r\n            &lt;div class=\"col-md-8\"&gt;\r\n                &lt;div class=\"card card-default\"&gt;\r\n                    &lt;div class=\"card-header\"&gt;Register&lt;\/div&gt;\r\n                    &lt;div class=\"card-body\"&gt;\r\n                        &lt;form&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"name\" class=\"col-md-4 col-form-label text-md-right\"&gt;Name&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"name\" type=\"text\" class=\"form-control\" v-model=\"name\" required autofocus&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"email\" class=\"col-md-4 col-form-label text-md-right\"&gt;E-Mail Address&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"email\" type=\"email\" class=\"form-control\" v-model=\"email\" required&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"password\" class=\"col-md-4 col-form-label text-md-right\"&gt;Password&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"password\" type=\"password\" class=\"form-control\" v-model=\"password\" required&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row\"&gt;\r\n                                &lt;label for=\"password-confirm\" class=\"col-md-4 col-form-label text-md-right\"&gt;Confirm Password&lt;\/label&gt;\r\n                                &lt;div class=\"col-md-6\"&gt;\r\n                                    &lt;input id=\"password-confirm\" type=\"password\" class=\"form-control\" v-model=\"password_confirmation\" required&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                            &lt;div class=\"form-group row mb-0\"&gt;\r\n                                &lt;div class=\"col-md-6 offset-md-4\"&gt;\r\n                                    &lt;button type=\"submit\" class=\"btn btn-primary\" @click=\"handleSubmit\"&gt;\r\n                                        Register\r\n                                    &lt;\/button&gt;\r\n                                &lt;\/div&gt;\r\n                            &lt;\/div&gt;\r\n                        &lt;\/form&gt;\r\n                    &lt;\/div&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p>Above we have the HTML for the registration form. Let\u2019s add the script for the component below the closing\u00a0template\u00a0tag:<\/p>\n<pre class=\"lang:default decode:true\">&lt;script&gt;\r\nexport default {\r\n    props : ['nextUrl'],\r\n    data(){\r\n        return {\r\n            name : \"\",\r\n            email : \"\",\r\n            password : \"\",\r\n            password_confirmation : \"\"\r\n        }\r\n    },\r\n    methods : {\r\n        handleSubmit(e) {\r\n            e.preventDefault()\r\n            if (this.password.length &lt;= 5) {\r\n                this.password = \"\"\r\n                this.password_confirmation = \"\"\r\n                return alert('Passwords must contain 6 or more characters')\r\n            }\r\n            if (this.password !== this.password_confirmation) {\r\n                this.password = \"\"\r\n                this.password_confirmation = \"\"\r\n                return alert('Passwords do not match')\r\n            }\r\n            let name = this.name\r\n            let email = this.email\r\n            let password = this.password\r\n            let c_password = this.password_confirmation\r\n            axios.post('api\/register', {name, email, password, c_password}).then(response =&gt; {\r\n                let data = response.data\r\n                localStorage.setItem('myStore.user', JSON.stringify(data.user))\r\n                localStorage.setItem('myStore.jwt', data.token)\r\n                if (localStorage.getItem('myStore.jwt') != null) {\r\n                    this.$emit('loggedIn')\r\n                    let nextUrl = this.$route.params.nextUrl\r\n                    this.$router.push((nextUrl != null ? nextUrl : '\/'))\r\n                }\r\n            })\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>NOTE: I added a check for the password and the confirmation characters length. It should be more than 5 characters.<br \/>\nThe register component operates similarly to the login component. We send the user data to the API for authentication and if we get a favourable response we save the token and user to\u00a0localStorage.<\/p>\n<p>Making the marketplace pages<br \/>\nWe had already defined the homepage in the last chapter and returned a list of available products. Now, we are going to make all the other store pages.<\/p>\n<p>Open the\u00a0resources\/js\/components\/SingleProduct.vue\u00a0file and paste in the following code:<\/p>\n<pre class=\"lang:default decode:true\">&lt;template&gt;\r\n    &lt;div class=\"container\"&gt;\r\n        &lt;div class=\"row\"&gt;\r\n            &lt;div class=\"col-md-8 offset-md-2\"&gt;\r\n                &lt;img :src=\"product.image\" :alt=\"product.name\"&gt;\r\n                &lt;h3 class=\"title\" v-html=\"product.name\"&gt;&lt;\/h3&gt;\r\n                &lt;p class=\"text-muted\"&gt;{{product.description}}&lt;\/p&gt;\r\n                &lt;h4&gt;\r\n                    &lt;span class=\"small-text text-muted float-left\"&gt;$ {{product.price}}&lt;\/span&gt;\r\n                    &lt;span class=\"small-text float-right\"&gt;Available Quantity: {{product.units}}&lt;\/span&gt;\r\n                &lt;\/h4&gt;\r\n                &lt;br&gt;\r\n                &lt;hr&gt;\r\n                &lt;router-link :to=\"{ path: '\/checkout?pid='+product.id }\" class=\"col-md-4 btn btn-sm btn-primary float-right\"&gt;Buy Now&lt;\/router-link&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {\r\n    data(){\r\n        return {\r\n            product : []\r\n        }\r\n    },\r\n    beforeMount(){\r\n        let url = `\/api\/products\/${this.$route.params.id}`\r\n        axios.get(url).then(response =&gt; this.product = response.data)      \r\n    }\r\n}\r\n&lt;\/script&gt;\r\n\r\n&lt;style scoped&gt;\r\n.small-text { font-size: 18px; }\r\n.title { font-size: 36px; }\r\n&lt;\/style&gt;<\/pre>\n<p>NOTE: USE backtick (`) INSTEAD OF apostroph (&#8216;) ON let url VARIABLE TO PARSE ${this.$route.params.id}<br \/>\nAbove we have the\u00a0product\u00a0as a data attribute, which we use to display information on the page like we did in the\u00a0Home.vue\u00a0file.<\/p>\n<p>In the components\u00a0script\u00a0we defined Vue\u2019s\u00a0beforeMount\u00a0method and fetched the product information there.\u00a0beforeMount\u00a0is called before the component is rendered, so it fetches the necessary data for rendering the component. If we get the data after the component has mounted, we would have errors before the component updates.<\/p>\n<p>Next, open the\u00a0resources\/js\/components\/Checkout.vue\u00a0file and paste the following code for the HTML template and style:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div class=\"container\"&gt;\r\n        &lt;div class=\"row\"&gt;\r\n            &lt;div class=\"col-md-8 offset-md-2\"&gt;\r\n                &lt;div class=\"order-box\"&gt;\r\n                    &lt;img :src=\"product.image\" :alt=\"product.name\"&gt;\r\n                    &lt;h2 class=\"title\" v-html=\"product.name\"&gt;&lt;\/h2&gt;\r\n                    &lt;p class=\"small-text text-muted float-left\"&gt;$ {{product.price}}&lt;\/p&gt;\r\n                    &lt;p class=\"small-text text-muted float-right\"&gt;Available Units: {{product.units}}&lt;\/p&gt;\r\n                    &lt;br&gt;\r\n                    &lt;hr&gt;\r\n                    &lt;label class=\"row\"&gt;&lt;span class=\"col-md-2 float-left\"&gt;Quantity: &lt;\/span&gt;&lt;input type=\"number\" name=\"units\" min=\"1\" :max=\"product.units\" class=\"col-md-2 float-left\" v-model=\"quantity\" @change=\"checkUnits\"&gt;&lt;\/label&gt;\r\n                &lt;\/div&gt;\r\n                &lt;br&gt;\r\n                &lt;div&gt;\r\n                    &lt;div v-if=\"!isLoggedIn\"&gt;\r\n                        &lt;h2&gt;You need to login to continue&lt;\/h2&gt;\r\n                        &lt;button class=\"col-md-4 btn btn-primary float-left\" @click=\"login\"&gt;Login&lt;\/button&gt;\r\n                        &lt;button class=\"col-md-4 btn btn-danger float-right\" @click=\"register\"&gt;Create an account&lt;\/button&gt;\r\n                    &lt;\/div&gt;\r\n                    &lt;div v-if=\"isLoggedIn\"&gt;\r\n                        &lt;div class=\"row\"&gt;\r\n                            &lt;label for=\"address\" class=\"col-md-3 col-form-label\"&gt;Delivery Address&lt;\/label&gt;\r\n                            &lt;div class=\"col-md-9\"&gt;\r\n                                &lt;input id=\"address\" type=\"text\" class=\"form-control\" v-model=\"address\" required&gt;\r\n                            &lt;\/div&gt;\r\n                        &lt;\/div&gt;\r\n                        &lt;br&gt;\r\n                        &lt;button class=\"col-md-4 btn btn-sm btn-success float-right\" v-if=\"isLoggedIn\" @click=\"placeOrder\"&gt;Continue&lt;\/button&gt;\r\n                    &lt;\/div&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n&lt;script&gt;\r\nexport default {\r\n    props : ['pid'],\r\n    data(){\r\n        return {\r\n            address : \"\",\r\n            quantity : 1,\r\n            isLoggedIn : null,\r\n            product : []\r\n        }\r\n    },\r\n    mounted() {\r\n        this.isLoggedIn = localStorage.getItem('myStore.jwt') != null\r\n    },\r\n    beforeMount() {\r\n        axios.get(`\/api\/products\/${this.pid}`).then(response =&gt; this.product = response.data)\r\n\r\n        if (localStorage.getItem('myStore.jwt') != null) {\r\n            this.user = JSON.parse(localStorage.getItem('myStore.user'))\r\n            axios.defaults.headers.common['Content-Type'] = 'application\/json'\r\n            axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('myStore.jwt')\r\n        }\r\n    },\r\n    methods : {\r\n        login() {\r\n            this.$router.push({name: 'login', params: {nextUrl: this.$route.fullPath}})\r\n        },\r\n        register() {\r\n            this.$router.push({name: 'register', params: {nextUrl: this.$route.fullPath}})\r\n        },\r\n        placeOrder(e) {\r\n            e.preventDefault()\r\n\r\n            let address = this.address\r\n            let product_id = this.product.id\r\n            let quantity = this.quantity\r\n\r\n            axios.post('api\/orders\/', {address, quantity, product_id})\r\n                    .then(response =&gt; this.$router.push('\/confirmation'))\r\n        },\r\n        checkUnits(e){\r\n            if (this.quantity &gt; this.product.units) {\r\n                this.quantity = this.product.units\r\n            }\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;\r\n&lt;style scoped&gt;\r\n.small-text { font-size: 18px; }\r\n.order-box { border: 1px solid #cccccc; padding: 10px 15px; }\r\n.title { font-size: 36px; }\r\n&lt;\/style&gt;<\/pre>\n<p>Above we defined the\u00a0beforeMount\u00a0method where we fetch product information. Then we have the\u00a0mounted\u00a0method where we check authentication status. In the\u00a0methods\u00a0property, we defined the\u00a0checkUnits\u00a0method that checks how many units the user wants to order, and then we define the\u00a0placeOrder\u00a0method that places the order.<\/p>\n<p>Next, open the\u00a0resources\/js\/components\/Confirmation.vue\u00a0file and paste the following code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;div class=\"container-fluid hero-section d-flex align-content-center justify-content-center flex-wrap ml-auto\"&gt;\r\n            &lt;h2&gt;\r\n                &lt;span class=\"title\"&gt;&lt;strong&gt;Thank You!&lt;\/strong&gt;&lt;\/span&gt;&lt;br&gt;\r\n                &lt;span class=\"medium-text\"&gt;Your order has been placed.&lt;\/span&gt;&lt;br&gt;\r\n                &lt;router-link :to=\"{name: 'userboard'}\" class=\"small-link\"&gt;\r\n                    See your orders\r\n                &lt;\/router-link&gt;\r\n            &lt;\/h2&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {}\r\n&lt;\/script&gt;\r\n\r\n&lt;style scoped&gt;\r\n.medium-text { font-size: 36px; }\r\n.small-link { font-size: 24px; text-decoration: underline; color: #777; }\r\n.product-box { border: 1px solid #cccccc; padding: 10px 15px; }\r\n.hero-section { height: 80vh; align-items: center; margin-top: -20px; margin-bottom: 20px; }\r\n.title { font-size: 60px; }\r\n&lt;\/style&gt;<\/pre>\n<p>This component displays a simple thank you message and provides a link for the users to navigate to their dashboard to see the orders they have placed and the status of these orders. Let\u2019s create the user dashboard next.<\/p>\n<p>Creating the user dashboard<br \/>\nThe user dashboard is where the users can see all their orders. Open the\u00a0resources\/js\/components\/UserBoard.vue\u00a0file and paste in the following code for the template and style:<\/p>\n<pre class=\"lang:default decode:true\">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;div class=\"container-fluid hero-section d-flex align-content-center justify-content-center flex-wrap ml-auto\"&gt;\r\n            &lt;h2 class=\"title\"&gt;All your orders&lt;\/h2&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"container\"&gt;\r\n            &lt;div class=\"row\"&gt;\r\n                &lt;div class=\"col-md-12\"&gt;\r\n                    &lt;br&gt;\r\n                    &lt;div class=\"row\"&gt;\r\n                        &lt;div class=\"col-md-4 product-box\" v-for=\"(order,index) in orders\" @key=\"index\"&gt;\r\n                            &lt;img :src=\"order.product.image\" :alt=\"order.product.name\"&gt;\r\n                            &lt;h5&gt;&lt;span v-html=\"order.product.name\"&gt;&lt;\/span&gt;&lt;br&gt;\r\n                                &lt;span class=\"small-text text-muted\"&gt;$ {{order.product.price}}&lt;\/span&gt;\r\n                            &lt;\/h5&gt;\r\n                            &lt;hr&gt;\r\n                            &lt;span class=\"small-text text-muted\"&gt;Quantity: {{order.quantity}}\r\n                                &lt;span class=\"float-right\"&gt;{{order.is_delivered == 1? \"shipped!\" : \"not shipped\"}}&lt;\/span&gt;\r\n                            &lt;\/span&gt;\r\n                            &lt;br&gt;&lt;br&gt;\r\n                            &lt;p&gt;&lt;strong&gt;Delivery address:&lt;\/strong&gt; &lt;br&gt;{{order.address}}&lt;\/p&gt;\r\n                        &lt;\/div&gt;\r\n                    &lt;\/div&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            user : null,\r\n            orders : []\r\n        }\r\n    },\r\n    beforeMount() {\r\n        this.user = JSON.parse(localStorage.getItem('myStore.user'))\r\n\r\n        axios.defaults.headers.common['Content-Type'] = 'application\/json'\r\n        axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('myStore.jwt')\r\n\r\n        axios.get(`api\/users\/${this.user.id}\/orders`)\r\n                .then(response =&gt; this.orders = response.data)\r\n    }\r\n}\r\n&lt;\/script&gt;\r\n&lt;style scoped&gt;\r\n.small-text { font-size: 14px; }\r\n.product-box { border: 1px solid #cccccc; padding: 10px 15px; }\r\n.hero-section { background: #ababab; height: 20vh; align-items: center; margin-bottom: 20px; margin-top: -20px; }\r\n.title { font-size: 60px; color: #ffffff; }\r\n&lt;\/style&gt;<\/pre>\n<p>In the code above, we fetch all the user\u2019s orders before the component is mounted, then loop through them and display them on the page.<\/p>\n<p>Creating the admin dashboard<br \/>\nThe admin dashboard is where new products are added, existing products modified and orders are set as delivered.<\/p>\n<p>For the admin board, we will use four different components, which we will mount based on the url a user is accessing. Let\u2019s see that in action. Open the\u00a0resources\/js\/components\/Admin.vue\u00a0file and paste in the following:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;div class=\"container-fluid hero-section d-flex align-content-center justify-content-center flex-wrap ml-auto\"&gt;\r\n            &lt;h2 class=\"title\"&gt;Admin Dashboard&lt;\/h2&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"container\"&gt;\r\n            &lt;div class=\"row\"&gt;\r\n                &lt;div class=\"col-md-3\"&gt;\r\n                    &lt;ul style=\"list-style-type:none\"&gt;\r\n                        &lt;li class=\"active\"&gt;&lt;button class=\"btn\" @click=\"setComponent('main')\"&gt;Dashboard&lt;\/button&gt;&lt;\/li&gt;\r\n                        &lt;li&gt;&lt;button class=\"btn\" @click=\"setComponent('orders')\"&gt;Orders&lt;\/button&gt;&lt;\/li&gt;\r\n                        &lt;li&gt;&lt;button class=\"btn\" @click=\"setComponent('products')\"&gt;Products&lt;\/button&gt;&lt;\/li&gt;\r\n                        &lt;li&gt;&lt;button class=\"btn\" @click=\"setComponent('users')\"&gt;Users&lt;\/button&gt;&lt;\/li&gt;\r\n                    &lt;\/ul&gt;\r\n                &lt;\/div&gt;\r\n                &lt;div class=\"col-md-9\"&gt;\r\n                    &lt;component :is=\"activeComponent\"&gt;&lt;\/component&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nimport Main from '..\/components\/admin\/Main'\r\nimport Users from '..\/components\/admin\/Users'\r\nimport Products from '..\/components\/admin\/Products'\r\nimport Orders from '..\/components\/admin\/Orders'\r\n\r\nexport default {\r\n    data() {\r\n        return {\r\n            user: null,\r\n            activeComponent: null\r\n        }\r\n    },\r\n    components: {\r\n        Main, Users, Products, Orders\r\n    },\r\n    beforeMount() {\r\n        this.setComponent(this.$route.params.page)\r\n        this.user = JSON.parse(localStorage.getItem('myStore.user'))\r\n        axios.defaults.headers.common['Content-Type'] = 'application\/json'\r\n        axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('myStore.jwt')\r\n    },\r\n    methods: {\r\n        setComponent(value) {\r\n            switch(value) {\r\n                case \"users\":\r\n                    this.activeComponent = Users\r\n                    this.$router.push({name: 'admin-pages', params: {page: 'users'}})\r\n                    break;\r\n                case \"orders\":\r\n                    this.activeComponent = Orders\r\n                    this.$router.push({name: 'admin-pages', params: {page: 'orders'}})\r\n                    break;\r\n                case \"products\":\r\n                    this.activeComponent = Products\r\n                    this.$router.push({name: 'admin-pages', params: {page: 'products'}})\r\n                    break;\r\n                default:\r\n                    this.activeComponent = Main\r\n                    this.$router.push({name: 'admin'})\r\n                    break;\r\n            }\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;\r\n\r\n&lt;style scoped&gt;\r\n.hero-section { height: 20vh; background: #ababab; align-items: center; margin-bottom: 20px; margin-top: -20px; }\r\n.title { font-size: 60px; color: #ffffff; }\r\n&lt;\/style&gt;<\/pre>\n<p>In the code above, we import and register four components, which we have not yet created. They\u2019ll be used as components inside\u00a0Admin.vue\u00a0parent component.<\/p>\n<p>In our template, we defined the navigation for switching between the components. Each navigation link calls the\u00a0setComponent\u00a0method and then passes a value to it. The\u00a0setComponent\u00a0method just sets the component using a\u00a0switch\u00a0statement.<\/p>\n<p>Let\u2019s create the first component for the Admin component. Create the\u00a0Main.vue\u00a0file in\u00a0resources\/js\/components\/admin\u00a0directory and paste the following into the file:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div class=\"row\"&gt;\r\n        &lt;div class=\"col-md-4 product-box d-flex align-content-center justify-content-center flex-wrap big-text\"&gt;\r\n            &lt;a href='\/admin\/orders'&gt;Orders ({{orders.length}})&lt;\/a&gt;\r\n        &lt;\/div&gt;\r\n        &lt;hr&gt;\r\n        &lt;div class=\"col-md-4 product-box d-flex align-content-center justify-content-center flex-wrap big-text\"&gt;\r\n            &lt;a href='\/admin\/products'&gt;Products ({{products.length}})&lt;\/a&gt;\r\n        &lt;\/div&gt;\r\n        &lt;div class=\"col-md-4 product-box d-flex align-content-center justify-content-center flex-wrap big-text\"&gt;\r\n            &lt;a href='\/admin\/users'&gt;Users ({{users.length}})&lt;\/a&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            user : null,\r\n            orders : [],\r\n            products : [],\r\n            users : []\r\n        }\r\n    },\r\n    mounted() {\r\n        axios.get('\/api\/users\/').then(response =&gt; this.users = response.data)\r\n        axios.get('\/api\/products\/').then(response =&gt; this.products = response.data)\r\n        axios.get('\/api\/orders\/').then(response =&gt; this.orders = response.data)\r\n    }\r\n}\r\n&lt;\/script&gt;\r\n\r\n&lt;style scoped&gt;\r\n.big-text { font-size: 28px; }\r\n.product-box { border: 1px solid #cccccc; padding: 10px 15px; height: 20vh }\r\n&lt;\/style&gt;<\/pre>\n<p>In the code above we are calling the APIs for users, orders and products, and returning their data.<\/p>\n<p>Create the\u00a0Orders.vue\u00a0file in\u00a0resources\/js\/components\/admin\u00a0and paste the following into the file:<\/p>\n<pre class=\"lang:default decode:true\">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;table class=\"table table-responsive table-striped\"&gt;\r\n            &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                    &lt;td&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;Product&lt;\/td&gt;\r\n                    &lt;td&gt;Quantity&lt;\/td&gt;\r\n                    &lt;td&gt;Cost&lt;\/td&gt;\r\n                    &lt;td&gt;Delivery Address&lt;\/td&gt;\r\n                    &lt;td&gt;is Delivered?&lt;\/td&gt;\r\n                    &lt;td&gt;Action&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/thead&gt;\r\n            &lt;tbody&gt;\r\n                &lt;tr v-for=\"(order,index) in orders\" @key=\"index\"&gt;\r\n                    &lt;td&gt;{{index+1}}&lt;\/td&gt;\r\n                    &lt;td v-html=\"order.product.name\"&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;{{order.quantity}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{order.quantity * order.product.price}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{order.address}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{order.is_delivered == 1? \"Yes\" : \"No\"}}&lt;\/td&gt;\r\n                    &lt;td v-if=\"order.is_delivered == 0\"&gt;&lt;button class=\"btn btn-success\" @click=\"deliver(index)\"&gt;Deliver&lt;\/button&gt;&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/tbody&gt;\r\n        &lt;\/table&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            orders : []\r\n        }\r\n    },\r\n    beforeMount(){\r\n        axios.get('\/api\/orders\/').then(response =&gt; this.orders = response.data)\r\n    },\r\n    methods: {\r\n        deliver(index) {\r\n            let order = this.orders[index]\r\n            axios.patch(`\/api\/orders\/${order.id}\/deliver`).then(response =&gt; {\r\n                this.orders[index].is_delivered = 1\r\n                this.$forceUpdate()\r\n            })\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>In\u00a0beforeMount\u00a0we fetch all the orders placed before the component is rendered.<\/p>\n<p>When the\u00a0Deliver\u00a0button is clicked, the\u00a0deliver\u00a0method is fired. We call the API for delivering orders. To get the change to reflect on the page instantly, we call\u00a0[$forceUpdate](https:\/\/vuejs.org\/v2\/api\/#vm-forceUpdate).<\/p>\n<p>Create the\u00a0Users.vue\u00a0file in\u00a0resources\/js\/components\/admin\u00a0and paste in the following code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;table class=\"table table-responsive table-striped\"&gt;\r\n            &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                    &lt;td&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;Name&lt;\/td&gt;\r\n                    &lt;td&gt;Email&lt;\/td&gt;\r\n                    &lt;td&gt;Joined&lt;\/td&gt;\r\n                    &lt;td&gt;Total Orders&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/thead&gt;\r\n            &lt;tbody&gt;\r\n                &lt;tr v-for=\"(user,index) in users\" @key=\"index\"&gt;\r\n                    &lt;td&gt;{{index+1}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{user.name}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{user.email}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{user.created_at}}&lt;\/td&gt;\r\n                    &lt;td&gt;{{user.orders.length}}&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/tbody&gt;\r\n        &lt;\/table&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script&gt;\r\nexport default {\r\n    data() {\r\n        return {\r\n            users : []\r\n        }\r\n    },\r\n    beforeMount() {\r\n        axios.get('\/api\/users\/').then(response =&gt; this.users = response.data)\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>Above we fetch all the user data and then display it on the page.<\/p>\n<p>Next, create the\u00a0Products.vue\u00a0file in\u00a0resources\/js\/components\/admin\u00a0and paste the following template code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div&gt;\r\n        &lt;table class=\"table table-responsive table-striped\"&gt;\r\n            &lt;thead&gt;\r\n                &lt;tr&gt;\r\n                    &lt;td&gt;&lt;\/td&gt;\r\n                    &lt;td&gt;Product&lt;\/td&gt;\r\n                    &lt;td&gt;Units&lt;\/td&gt;\r\n                    &lt;td&gt;Price&lt;\/td&gt;\r\n                    &lt;td&gt;Description&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/thead&gt;\r\n            &lt;tbody&gt;\r\n                &lt;tr v-for=\"(product,index) in products\" @key=\"index\" @dblclick=\"editingItem = product\"&gt;\r\n                    &lt;td&gt;{{index+1}}&lt;\/td&gt;\r\n                    &lt;td v-html=\"product.name\"&gt;&lt;\/td&gt;\r\n                    &lt;td v-model=\"product.units\"&gt;{{product.units}}&lt;\/td&gt;\r\n                    &lt;td v-model=\"product.price\"&gt;{{product.price}}&lt;\/td&gt;\r\n                    &lt;td v-model=\"product.price\"&gt;{{product.description}}&lt;\/td&gt;\r\n                &lt;\/tr&gt;\r\n            &lt;\/tbody&gt;\r\n        &lt;\/table&gt;\r\n        &lt;modal @close=\"endEditing\" :product=\"editingItem\" v-show=\"editingItem != null\"&gt;&lt;\/modal&gt;\r\n        &lt;modal @close=\"addProduct\"  :product=\"addingProduct\" v-show=\"addingProduct != null\"&gt;&lt;\/modal&gt;\r\n        &lt;br&gt;\r\n        &lt;button class=\"btn btn-primary\" @click=\"newProduct\"&gt;Add New Product&lt;\/button&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n&lt;script&gt;\r\nimport Modal from '.\/ProductModal'\r\n\r\nexport default {\r\n    data() {\r\n        return {\r\n            products: [],\r\n            editingItem: null,\r\n            addingProduct: null\r\n        }\r\n    },\r\n    components: {Modal},\r\n    beforeMount() {\r\n        axios.get('\/api\/products\/').then(response =&gt; this.products = response.data)\r\n    },\r\n    methods: {\r\n        newProduct() {\r\n            this.addingProduct = {\r\n                name: null,\r\n                units: null,\r\n                price: null,\r\n                image: null,\r\n                description: null,\r\n            }\r\n        },\r\n        endEditing(product) {\r\n            this.editingItem = null\r\n\r\n            let index = this.products.indexOf(product)\r\n            let name = product.name\r\n            let units = product.units\r\n            let price = product.price\r\n            let description = product.description\r\n\r\n            axios.put(`\/api\/products\/${product.id}`, {name, units, price, description})\r\n            .then(response =&gt; this.products[index] = product)\r\n        },\r\n        addProduct(product) {\r\n            this.addingProduct = null\r\n\r\n            let name = product.name\r\n            let units = product.units\r\n            let price = product.price\r\n            let description = product.description\r\n            let image = product.image \r\n\r\n            axios.post('\/api\/products\/', {name, units, price, description, image})\r\n            .then(response =&gt; this.products.push(product))\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>In the\u00a0methods\u00a0property we defined the following methods:<\/p>\n<p>newProduct()\u00a0\u2013 called when we want to initiate a new local product object.<br \/>\nendEditing()\u00a0\u2013 called when we are done editing a product.<br \/>\naddProduct()\u00a0\u2013 called when we are want to add a new product.<br \/>\nWe imported a\u00a0ProductModal\u00a0component, which we will create next. The modal will be used to edit an existing or create a new product. Double clicking on a product listed fires up the modal for editing the product.<\/p>\n<p>Create the\u00a0ProductModal.vue\u00a0file in\u00a0resources\/js\/components\/admin\u00a0and paste in the following template and style code:<\/p>\n<pre class=\"lang:default decode:true \">&lt;template&gt;\r\n    &lt;div class=\"modal-mask\"&gt;\r\n        &lt;div class=\"modal-wrapper\"&gt;\r\n            &lt;div class=\"modal-container\"&gt;\r\n                &lt;div class=\"modal-header\"&gt;\r\n                    &lt;slot name=\"header\" v-html=\"data.name\"&gt;&lt;\/slot&gt;\r\n                &lt;\/div&gt;\r\n                &lt;div class=\"modal-body\"&gt;\r\n                    &lt;slot name=\"body\"&gt;\r\n                        Name: &lt;input type=\"text\" v-model=\"data.name\"&gt;\r\n                        Units: &lt;input type=\"text\" v-model=\"data.units\"&gt;\r\n                        Price: &lt;input type=\"text\" v-model=\"data.price\"&gt;\r\n                        &lt;textarea v-model=\"data.description\" placeholder=\"description\"&gt;&lt;\/textarea&gt;\r\n                        &lt;span &gt;\r\n                            &lt;img :src=\"data.image\" v-show=\"data.image != null\"&gt;\r\n                            &lt;input type=\"file\" id=\"file\" @change=\"attachFile\"&gt;\r\n                        &lt;\/span&gt;\r\n                    &lt;\/slot&gt;\r\n                &lt;\/div&gt;\r\n                &lt;div class=\"modal-footer\"&gt;\r\n                    &lt;slot name=\"footer\"&gt;\r\n                        &lt;button class=\"modal-default-button\" @click=\"uploadFile\"&gt;\r\n                            Finish\r\n                        &lt;\/button&gt;\r\n                    &lt;\/slot&gt;\r\n                &lt;\/div&gt;\r\n            &lt;\/div&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n&lt;script&gt;\r\nexport default {\r\n    props: ['product'],\r\n    data() {\r\n        return {\r\n            attachment: null\r\n        }\r\n    },\r\n    computed: {\r\n        data: function() {\r\n            if (this.product != null) {\r\n                return this.product\r\n            }\r\n            return {\r\n                name: \"\",\r\n                units: \"\",\r\n                price: \"\",\r\n                description: \"\",\r\n                image: false\r\n            }\r\n        }\r\n    },\r\n    methods: {\r\n        attachFile(event) {\r\n            this.attachment = event.target.files[0];\r\n        },\r\n        uploadFile(event) {\r\n            if (this.attachment != null) {\r\n                var formData = new FormData();\r\n                formData.append(\"image\", this.attachment)\r\n                let headers = {'Content-Type': 'multipart\/form-data'}\r\n                axios.post('\/api\/upload-file', formData, {headers}).then(response =&gt; {\r\n                    this.product.image = response.data\r\n                    this.$emit('close', this.product)\r\n                })\r\n            } else {\r\n                this.$emit('close', this.product)\r\n            }\r\n        }\r\n    }\r\n}\r\n&lt;\/script&gt;\r\n&lt;style scoped&gt;\r\n.modal-mask {\r\n    position: fixed;\r\n    z-index: 9998;\r\n    top: 0;\r\n    left: 0;\r\n    width: 100%;\r\n    height: 100%;\r\n    background-color: rgba(0, 0, 0, .5);\r\n    display: table;\r\n    transition: opacity .3s ease;\r\n}\r\n.modal-wrapper {\r\n    display: table-cell;\r\n    vertical-align: middle;\r\n}\r\n.modal-container {\r\n    width: 300px;\r\n    margin: 0px auto;\r\n    padding: 20px 30px;\r\n    background-color: #fff;\r\n    border-radius: 2px;\r\n    box-shadow: 0 2px 8px rgba(0, 0, 0, .33);\r\n    transition: all .3s ease;\r\n    font-family: Helvetica, Arial, sans-serif;\r\n}\r\n.modal-header h3 {\r\n    margin-top: 0;\r\n    color: #42b983;\r\n}\r\n.modal-body {\r\n    margin: 20px 0;\r\n}\r\n.modal-default-button {\r\n    float: right;\r\n}\r\n.modal-enter {\r\n    opacity: 0;\r\n}\r\n.modal-leave-active {\r\n    opacity: 0;\r\n}\r\n.modal-enter .modal-container,\r\n.modal-leave-active .modal-container {\r\n    -webkit-transform: scale(1.1);\r\n    transform: scale(1.1);\r\n}\r\n&lt;\/style&gt;<\/pre>\n<p>When the modal receives a\u00a0product\u2019s data, it pre-fills each field with the data. When we attach an image and submit the modal\u2019s form, it is uploaded and the url for the image is returned to us.<\/p>\n<p>We update the image attribute of the product with the url, then emit a\u00a0close\u00a0event and return the product with it. If no image is attached, we emit a\u00a0close\u00a0event and return the product data along with it.<\/p>\n<p>This modal component is an example provided in Vue documentation\u00a0<a href=\"https:\/\/vuejs.org\/v2\/examples\/modal.html\">here<\/a><\/p>\n<p>Payments<br \/>\nThere are many payment options for e-commerce platforms. You choose depending on your needs and what is available in your country. Many popular payment processors like Stripe have excellent guides on integrating into a JavaScript or PHP application which you can use. This tutorial won\u2019t cover that though, you can take it as an exercise for practise.<\/p>\n<p>Building our application<br \/>\nWe are done building our application. The next thing to do will be to compile our Vue application and serve our Laravel backend. Run the command to build the application.<\/p>\n<p>Admin user:<br \/>\nemail: admin@admin.com<br \/>\nname: Admin<br \/>\npassword: secret<\/p>\n<p>Create\/Register a new user:<br \/>\nemail: advcha@yahoo.com<br \/>\nname: Satria<br \/>\npassword: satria<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ref: https:\/\/blog.pusher.com\/ecommerce-laravel-vue-part-1\/ In this article, we will cover how you can use Laravel to build a simple e-commerce application. After this tutorial, you should know how to use Laravel and Vue to make a web application and understand the basics of making an online store. With the advent of the internet, many regular things became &hellip; <a href=\"https:\/\/myprojects.advchaweb.com\/index.php\/2019\/01\/31\/create-laravel-store-with-vue\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Create Laravel Store with Vue&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[82,83],"tags":[],"class_list":["post-3482","post","type-post","status-publish","format-standard","hentry","category-laravel-2","category-vue"],"_links":{"self":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/3482","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/comments?post=3482"}],"version-history":[{"count":31,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/3482\/revisions"}],"predecessor-version":[{"id":3484,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/posts\/3482\/revisions\/3484"}],"wp:attachment":[{"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/media?parent=3482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/categories?post=3482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/myprojects.advchaweb.com\/index.php\/wp-json\/wp\/v2\/tags?post=3482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}