...
We will leverage on Bootstrap in this project, so run the following command to get it and jQuery (Bootstrap relies on this) setup.
...
Navigate to the main.js in the src directory and add the following code
Code Block | ||
---|---|---|
| ||
import 'bootstrap'; import 'bootstrap/dist/css/bootstrap.min.css'; |
...
Open the App.vue file in the src directory and edit to look like this:
Code Block | ||
---|---|---|
| ||
<template> <div id="app"> <Products /> </div> </template> <script> import Products from './components/Products.vue' export default { name: 'App', components: { Products } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; margin-top: 60px; } </style> |
...
Open the Products file in the components directory and add the following code:
Code Block | ||
---|---|---|
| ||
<template> <div class="container"> <div class="card"> <div class="card-header"> All products </div> <div class="card-body"> pRODUCTS </div> </div> </div> </template> <script> export default { name: 'Products', methods: { getAllProducts() { const baseUrl = process.env.VUE_APP_API_BASE_URL; this.axios.get(baseUrl + '/api/product').then(response => { console.log(response); }) } }, mounted() { this.getAllProducts(); } } </script> |
...
Edit the Product.vue file to look like this:
Code Block | ||
---|---|---|
| ||
<template> <div> <h1>Merce's store</h1> <hr> <div class="row"> <div class="col-sm-4" v-for="product in products" v-bind:key="product.id"> <div class="card"> <div class="card-body"> <h5 class="card-title">{{ product.name }}</h5> <p class="card-text">Selling for ₦{{Intl.NumberFormat().format(product.price)}}</p> <a href="#" class="btn btn-primary" @click="addProductToCart(product)">Add to cart</a> </div> </div> </div> </div> </div> </template> <script> export default { name: 'Products', data() { return { products: [] } }, methods: { addProductToCart() { }, getAllProducts() { const baseUrl = process.env.VUE_APP_API_BASE_URL; this.axios.get(baseUrl + '/api/product').then(response => { this.products = response.data; }) } }, mounted() { this.getAllProducts(); } } </script> |
...
Add the following code to the Cart.vue file in the components directory:
Code Block | ||
---|---|---|
| ||
<template> <div> <h1>Basket</h1> <hr> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Item</th> <th scope="col">Price</th> <th scope="col">Quantity</th> </tr> </thead> <tbody> <tr> <th scope="row">1</th> <td>JDL EXTREME</td> <td>600000</td> <td>x2</td> </tr> </tbody> </table> </div> </template> <script> export default { name: 'Cart', data() { return { items: [] } }, methods: { }, created() { } } </script> |
...
We have implemented the products and cart view, developed in their own component. This is done for modularity. We need a way for both components to communicate such that the once the “Add to cart” button is clicked in the products view, the cart reflects the added product.
...
Update your main.js file in the src directory to look like this:
Code Block | ||
---|---|---|
| ||
import Vue from 'vue' import App from './App.vue' import 'bootstrap'; import 'bootstrap/dist/css/bootstrap.min.css'; import axios from 'axios' import VueAxios from 'vue-axios' Vue.config.productionTip = false Vue.use(VueAxios, axios) export const bus = new Vue(); window.Vue = Vue; new Vue({ render: h => h(App), }).$mount('#app') |
...
Let us add a button to send the cart item to our backend and the functionality to load the checkout url in our browser. Update the Cart.vue to look like this.
Code Block | ||
---|---|---|
| ||
<template> <div> <h1>Basket</h1> <hr> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Item</th> <th scope="col">Price</th> <th scope="col">Quantity</th> </tr> </thead> <tbody> <tr v-for="(item, index) in cartItems" v-bind:key="item.id"> <th scope="row">{{index + 1}}</th> <td>{{item.name}}</td> <td>₦{{Intl.NumberFormat().format(item.price)}}</td> <td>x{{item.quantity}}</td> </tr> </tbody> </table> <div class="row"> <div class="col-sm-6"> <button class="btn btn-primary" @click="payForCartItems" :disabled="items.length <= 0">Pay now</button> </div> <div class="col-sm-6"> Total: ₦{{Intl.NumberFormat().format(getCartTotal())}} </div> </div> </div> </template> <script> import { eventBus } from '../main' export default { name: 'Cart', data() { return { items: [] } }, methods: { addProductToCart(product) { if (this.items.length > 0) { const productIndex = this.items.findIndex(productInCart => productInCart.id === product.id); if (productIndex > -1) { let productFound = this.items[productIndex]; productFound.quantity++; productFound.totalPrice = productFound.quantity * productFound.price; return window.Vue.set(this.items, productIndex, product); } } product.quantity = 1; product.totalPrice = product.quantity * product.price; this.items.push(product); }, payForCartItems() { const cartData = { totalAmount: this.getCartTotal(), paymentDescription: "payment for item's merce's store", customerName: "Fake name", customerEmail: "Fakeemail@fakeemail.com" }; const baseUrl = process.env.VUE_APP_API_BASE_URL; this.axios.post(baseUrl + '/api/product/process-payment', cartData).then(response => { if (response.status === 200) { return window.open(response.data, '_blank').focus(); } return alert("Failed to receive checkout url"); }) }, getCartTotal() { return this.items.reduce((a, b) => +a + +b.totalPrice, 0); } }, created() { eventBus.$on('add-product-to-cart', this.addProductToCart); }, computed: { cartItems() { return this.items; } } } </script> |
...