Shopping Cart Using Vue js 3 Composition API and Pinia Part 2
In the second part of this project, we will add the home component, and display the products, we will also add, update, and remove products from the cart.
Create the ProductListItem component
Inside components, we add a new file ProductListItem.vue.
<template>
<div class="col-md-4 mb-2">
<div class="card" style="width: '18rem'">
<img :src="product.image" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title">{{product.name}}</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<button
@click="data.addToCart(product)"
class="btn btn-primary">
<i class="bi bi-cart-check"></i> add to cart
</button>
</div>
</div>
</div>
</template>
<script setup>
import { useShoppingStore } from '../stores'
//get props
const props = defineProps({
product: {
type: Object,
required: true
}
});
//get store
const data = useShoppingStore();
</script>
<style>
</style>
Create the ProductList component
Inside components, we add a new file ProductList.vue.
<template>
<div className='row my-4'>
<ProductListItem v-for="product in data.products"
:key="product.id" :product="product" />
</div>
</template>
<script setup>
import ProductListItem from './ProductListItem.vue'
import { useShoppingStore } from '../stores'
//get products from store
const data = useShoppingStore();
</script>
<style>
</style>
Create the Home component
Inside components, we add a new file Home.vue.
<template>
<ProductList />
</template>
<script setup>
import ProductList from "./ProductList.vue";
</script>
<style>
</style>
Create the Cart component
Inside components, we add a new file Cart.vue.
<template>
<div class="row my-4">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Image</th>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
<th>Subtotal</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="item in data.getCartItems" :key="item.id">
<td>{{item.id}}</td>
<td>
<img :src="item.image"
class="fluid rounded"
width="60"
height="60"
:alt="item.name" />
</td>
<td>
{{item.name}}
</td>
<td>
<i
@click="data.incrementQ(item)"
class="bi bi-caret-up"></i>
<span class="mx-2">
{{item.quantity}}
</span>
<i
@click="data.decrementQ(item)"
class="bi bi-caret-down"></i>
</td>
<td>
${{item.price}}
</td>
<td>
${{item.price * item.quantity}}
</td>
<td>
<i
@click="data.removeFromCart(item)"
class="bi bi-cart-x text-danger"></i>
</td>
</tr>
<tr>
<th colSpan="3" class="text-center">
Total
</th>
<td colSpan="3" class="text-center">
<span class="badge bg-danger rounded-pill">
${{ data.cartItems.reduce((acc,item) => acc += item.price * item.quantity,0) }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { useShoppingStore } from "../stores"
//get store
const data = useShoppingStore();
</script>
<style>
i{
cursor: pointer;
}
</style>
Update the App component
Inside the src folder, we update the file App.vue, you can download the source code from here.
<template>
<div class="container">
<Header />
<router-view></router-view>
</div>
</template>
<script setup>
import Header from './components/Header.vue'
</script>
<style>
</style>