Today we will make one more step in our creating e-commerce store journey. In our last part, we already added features that fetch and render product data, and now we will add more improvements to our online store. We will build functions that will add products to the user's cart and wishlist, and also update our cart and wishlist pages so that they show product lists and users can modify them. Yeah, as usual, much work to do, so let's define a work plan and jump in.
- Implement the "Add to Cart" and the "Add to Wishlist" features.
- Improve the Cart Page, where users can view and manage the items in their shopping cart, update quantities, remove items, and proceed to checkout.
- Build the Wishlist Page functionality, displaying the products the user has added to their wishlist, with options to move items to the cart or remove them from the wishlist.
With the work plan laid out, let's dive into the implementation details and start bringing these features to life. First up, we'll tackle the core functionality of adding products to the cart and wishlist.
1. Implement the "Add to Cart" and the "Add to Wishlist" features.
Let's clarify: we do not have the user profile page or something like that, we will not store any user data on our database, that is why we will save cart and wishlist data on the user side and use local storage for that.
Okay, let's do it. Open the "products" store and add new "shoppingCart" and "wishlist" variables as an empty array. Next create the "aAddToShoppingCart" action, which will check if there is a "shopping-cart" item in local storage, yes it will rewrite our shopping cart variable and then add a new item to the cart and finally update the value in the local storage. Also, we will return some sort of response so that we know what type of message to show.
aAddToShoppingCart(product) {
const shoppingCart = localStorage.getItem('shopping-cart');
if (shoppingCart) {
this.shoppingCart = JSON.parse(shoppingCart);
} else {
localStorage.setItem('shopping-cart', JSON.stringify(this.shoppingCart));
}
const productExist = this.shoppingCart.find(el => el === product.id);
if (productExist) {
return {code: 400, msg: 'Product already in cart'};
}
this.shoppingCart.push(product.id);
localStorage.setItem('shopping-cart', JSON.stringify(this.shoppingCart));
return {code: 200, msg: 'Product added to cart'};
},
I think that our wishlist will have the same saving process but with a wishlist array.
aAddToWishlist(product) {
const wishlist = localStorage.getItem('wishlist');
if (wishlist) {
this.wishlist = JSON.parse(wishlist);
} else {
localStorage.setItem('wishlist', JSON.stringify(this.wishlist));
}
const productExist = this.wishlist.find(el => el === product.id);
if (productExist) {
return {code: 400, msg: 'Product already in wishlist'};
}
this.wishlist.push(product.id);
localStorage.setItem('wishlist', JSON.stringify(this.wishlist));
return {code: 200, msg: 'Product added to wishlist'};
},
Great. We need to add this functionality to each "Add to Cart" and "Add to Wishlist" button. Let's work with the Product Card component, inside the methods section create a new function "addToCart" that will simply call our "aAddToShoppingCart" action, and then depend on the result code to show a notification.
addToCart() {
const result = this.productsStore.aAddToShopingCart(this.product);
if (result.code === 200) {
this.baseStore.aSetNotification({
type: 'success',
msg: 'Product was added to Cart!'
})
} else if (result.code === 400) {
this.baseStore.aSetNotification({
type: 'warning',
msg: result.msg
})
}
},
The same function should be with the wishlist button, we only need to change the action.
Next, we need to add these functions to click events in our template.
<li class="overlay__list--item icon-left" @click="addToWishlist">
<NuxtIcon name="heart-regular" size="20" class="overlay__list--icon"/>
</li>
<li class="overlay__list--item">
<button class="overlay__list--button" @click="addToCart">Add to cart</button>
</li>
Do not forget to restart the dev server and check the result, also please add this functionality on your own to other components (preview modal, product page...), and we can move on.
2. Improve the Cart Page, where users can view and manage the items in their shopping cart, update quantities, remove items, and proceed to checkout.
In our Cart Page, we have a list of items to sell, but they are static for now. Let's create a "productsList" array that will contain our products, then in the mounted lifecycle hook, we will call action to get the whole products list and filter only products that were added to our shopping cart.
methods: {
prepareCartList() {
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);
}
})
}
}
},
async mounted() {
const productsStore = useProductsStore();
await productsStore.aGetAllProducts();
this.prepareCartList();
}
Also, we need to add a possibility to remove the product from the cart, we will create an "aRemoveFromCart" action in the products store that will find and delete items from local storage and after that save the modified array.
aRemoveFromCart(product) {
const index = this.shopingCart.indexOf(product.id);
if (index > -1) {
this.shopingCart.splice(index, 1);
}
localStorage.setItem('shopping-cart', JSON.stringify(this.shopingCart));
return {code: 200, msg: 'Product removed from cart'};
}
Then inside the Cart page, we will create a "removeProduct" function that will call this action and show the result message.
removeProduct(product) {
const result = this.productsStore.aRemoveFromCart(product);
if (result.code === 200) {
this.baseStore.aSetNotification({
type: 'success',
msg: 'Product was removed from Cart!'
})
this.prepareCartList();
}
},
And the final touch, we need to remove the static list and replace it with dynamic that will render the products list array.
<div class="table-body">
<ul class="table-body__list" v-for="(product, index) in productsList" :key="index">
<li class="table-body__list--item product">
<NuxtLink to="/shop/product" class="table-body__list--link">
<img :src="product.image" :alt="product.name" :title="product.name">
</NuxtLink>
<NuxtLink :to="`/shop/${product.id}`" class="table-body__list--link">
{{ product.name }}
</NuxtLink>
</li>
<li class="table-body__list--item price">{{ product.price }}$</li>
<li class="table-body__list--item quantity">{{ product.quantity }}</li>
<li class="table-body__list--item total">{{ product.price * product.quantity }}$</li>
<li class="table-body__list--item remove">
<button class="table-body__list--item--btn" @click="removeProduct(product)">
<NuxtIcon name="trash-can-solid" size="20" class="table-body__list--icon"/>
</button>
</li>
</ul>
</div>
That's it, now we can add a few items to the cart, then open the cart and check the result or remove them.
3. Build the Wishlist Page functionality, displaying the products the user has added to their wishlist, with options to move items to the cart or remove them from the wishlist.
All most the same functionality should be added:
- remove the item from the wishlist;
- prepare a list for rendering;
- prepopulate products array;
- update list array with dynamic data;
<script>
import { useProductsStore } from "@/store/products";
import { useBaseStore } from "@/store/base";
import Breadcrumbs from "../../components/common/Breadcrumbs.vue";
export default {
name: "Wishlist",
components: {
Breadcrumbs,
},
data() {
return {
productsList: [],
}
},
computed: {
productsStore() {
return useProductsStore();
},
baseStore() {
return useBaseStore();
},
},
methods: {
removeProduct(product) {
const result = this.productsStore.aRemoveProductFromWishlist(product);
if (result.code === 200) {
this.baseStore.aSetNotification({
type: 'success',
msg: 'Product was removed from Wishlist!'
})
this.prepareWishlist();
}
},
prepareWishlist() {
this.productsList = [];
const productIds = JSON.parse(localStorage.getItem('wishlist'));
if (productIds && productIds.length > 0) {
this.productsStore.gProductsList.forEach(product => {
if (productIds.includes(product.id)) {
this.productsList.push(product);
}
})
}
}
},
async mounted() {
const productsStore = useProductsStore();
await productsStore.aGetAllProducts();
this.prepareWishlist();
}
}
</script>
Also, we need to remember that we have to add remove item action to the products store.
aRemoveProductFromWishlist(product) {
const index = this.wishlist.indexOf(product.id);
if (index > -1) {
this.wishlist.splice(index, 1);
}
localStorage.setItem('wishlist', JSON.stringify(this.wishlist));
return {code: 200, msg: 'Product removed from wishlist'}
}
And one more thing, we have a "Buy" button, this button should remove an item from the wishlist and add that item to the cart list. For that, we will add a new action to the products store that will do all that process independently.
aAddToCartFromWishlist(product) {
const shoppingCart = localStorage.getItem('shopping-cart');
if (shoppingCart) {
this.shoppingCart = JSON.parse(shoppingCart);
} else {
localStorage.setItem('shopping-cart', JSON.stringify(this.shoppingCart));
}
const productExist = this.shoppingCart.find(el => el === product.id);
if (productExist) {
return {code: 400, msg: 'Product already in cart'};
}
this.shoppingCart.push(product.id);
localStorage.setItem('shopping-cart', JSON.stringify(this.shoppingCart));
const index = this.wishlist.indexOf(product.id);
if (index > -1) {
this.wishlist.splice(index, 1);
}
localStorage.setItem('wishlist', JSON.stringify(this.wishlist));
return {code: 200, msg: 'Product added to cart'}
}
Now, save all the changes and check the result.
In this part of our e-commerce store development journey, we have implemented several critical features that enhance the user experience and functionality of our online shopping platform. By adding the "Add to Cart" and "Add to Wishlist" functionalities, we empowered users to manage their desired products, paving the way for a seamless shopping experience.
Overall, the implementation of these features has brought us closer to creating a comprehensive and user-friendly e-commerce store. Stay tuned, as our next step will be creating a simple checkout process.
If you would need a source code for this tutorial you can get it here.