As you've seen in the title, in this article we will work on our Checkout page. We will finish with our form, also configure data receiving from the user, and send sale requests to the server. That will be an interesting article because we will work less on the template and more on component functionality. So let's start!
First of all, we need to configure our "json-server" so that it can accept sale data, for that open the db.json file and add new array "sales" for example, after that restart your server.
"sales": []
When you start your "json-server" you should see that there appeared new endpoint "sales". Now we can use that endpoint to save there our orders.
We need to add a new HTTP function that will post data to that endpoint. Open the products.service.js file in the services folder and add a new "sale" function, that will accept the payload and send that payload to the sale endpoint.
export const sale = (payload) =>
HTTP.post('/sales', payload).then(({data}) => data )
I think we can say that we finished with preparation and now we can continue with the checkout page and products store. First, open the products store, we need to add an asynchronous "aPlaceOrder" action that will call our sale function and send data, we will be sure that this action will return for example a code with the message so that we can show a correct notification.
async aPlaceOrder(checkoutData) {
await sale(checkoutData)
.then((data) => {
console.log('data', data);
})
.catch((error) => {
console.log(error);
})
return {code: 200, msg: 'Order was placed successfully!'};
}
Now, the most important part, we need to open the index.vue file from the checkout folder and start with the mounted lifecycle hook. We will fetch the product list and prepare data for the summary section.
async mounted() {
const productsStore = useProductsStore();
await productsStore.aGetAllProducts();
this.prepareProducts();
}
We will use the same prepare function as in the cart and wishlist pages.
prepareProducts() {
this.productsList = [];
const productIds = JSON.parse(localStorage.getItem('shopping-cart'));
if (productIds && productIds.length > 0) {
this.productsStore.gProductsList.forEach(product => {
if (productIds.includes(product.id)) {
this.productsList.push(product);
}
})
}
},
Next, modify the summary section in our template so that we can check the result.
<div class="checkout__content--summary">
<h5>YOUR ORDER</h5>
<div class="subtotal" v-for="product in productsList" :key="product.id">
<p>{{ product.name }} </p>
<p class="subtotal__price">{{ product.price * product.quantity }}$</p>
</div>
<p class="total">Total: <span>{{ sum }}$</span></p>
</div>
Great, now we need to create a "checkoutData" variable that will store data about all the fields in our checkout form, and add a "v-model" directive to each input field. And final touch is our "placeOrder" function that will be triggered when "place order" button clicked. In that function, we will check if the cart is not empty because in that case we should not send any requests and if all fields in form have values. If everything is fine we will prepare a product list and send that list with the client data to the server, and then clear fields and cart and show the result notification.
async placeOrder() {
if (!this.productsStore.gShopingCart.length) {
this.baseStore.aSetNotification({
type: 'warning',
msg: 'Please add some products to cart!'
})
return;
}
if (
this.checkoutData.firstName
&& this.checkoutData.lastName
&& this.checkoutData.phone
&& this.checkoutData.email
&& this.checkoutData.city
&& this.checkoutData.country
&& this.checkoutData.address
) {
this.checkoutData.products = this.productsList.map(product => {
return {
id: product.id,
quantity: product.quantity
}
});
const result = await this.productsStore.aPlaceOrder(this.checkoutData);
if (result.code === 200) {
localStorage.setItem('shopping-cart', JSON.stringify([]));
this.productsStore.aSetShopingCart([]);
this.prepareProducts();
this.checkoutData = {
firstName: '',
lastName: '',
phone: '',
email: '',
city: '',
country: '',
address: '',
products: []
}
this.baseStore.aSetNotification({
type: 'success',
msg: 'Order was placed successfully!'
})
this.$router.push('/shop');
} else if (result.code === 400) {
this.baseStore.aSetNotification({
type: 'warning',
msg: result.msg
})
}
} else {
this.baseStore.aSetNotification({
type: 'warning',
msg: 'All fields are required!'
})
}
}
Awesome. Now let's restart our dev servers and check the result. We will add some products to the cart, fill in all the user data, and press the "Place Order" button.
Looks like everything works correctly, we were redirected to the shop page, our cart is empty and a notification was shown. Let's check our database!
"sales": [
{
"id": "c8fe",
"firstName": "Test",
"lastName": "User",
"phone": "+123456789",
"email": "test@email.com",
"city": "New York",
"country": "United States",
"address": "Brooklyn",
"products": [
{
"id": "1",
"quantity": 3
},
{
"id": "2",
"quantity": 3
}
]
}
]
Great job, we have all the data that we need to start working with the order.
Overall, the checkout functionality is a crucial component of any e-commerce platform, and our implementation has provided a seamless and user-friendly experience for customers to complete their purchases. With this feature in place, we can continue to build upon our e-commerce store, adding more advanced features and optimizations to deliver an exceptional online shopping experience.
If you would need a source code for this tutorial you can get it here.
Top comments (0)