In this module, we will build a fully functional e-commerce website using Vue.js. This project will help you apply the concepts learned in previous modules and gain hands-on experience in developing a real-world application.

Objectives

  • Create a user-friendly interface for browsing products.
  • Implement a shopping cart functionality.
  • Handle user authentication and authorization.
  • Integrate with a backend API for product data and order processing.
  • Deploy the application to a production environment.

Prerequisites

Before starting this project, ensure you have a good understanding of the following concepts:

  • Vue.js basics (template syntax, data binding, computed properties, etc.)
  • Vue.js components and component communication
  • Vue Router for navigation
  • Vuex for state management
  • Basic knowledge of HTML, CSS, and JavaScript

Project Structure

Here is the structure of our e-commerce project:

ecommerce-website/
├── public/
│   ├── index.html
├── src/
│   ├── assets/
│   ├── components/
│   │   ├── ProductList.vue
│   │   ├── ProductItem.vue
│   │   ├── ShoppingCart.vue
│   │   ├── Checkout.vue
│   ├── views/
│   │   ├── Home.vue
│   │   ├── ProductDetail.vue
│   │   ├── Cart.vue
│   │   ├── Login.vue
│   │   ├── Register.vue
│   ├── store/
│   │   ├── index.js
│   ├── router/
│   │   ├── index.js
│   ├── App.vue
│   ├── main.js
├── package.json
├── README.md

Step-by-Step Guide

Step 1: Setting Up the Project

  1. Create a new Vue project:
    vue create ecommerce-website
    
  2. Navigate to the project directory:
    cd ecommerce-website
    

Step 2: Setting Up Vue Router

  1. Install Vue Router:

    npm install vue-router
    
  2. Create the router configuration file (src/router/index.js):

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import Home from '../views/Home.vue';
    import ProductDetail from '../views/ProductDetail.vue';
    import Cart from '../views/Cart.vue';
    import Login from '../views/Login.vue';
    import Register from '../views/Register.vue';
    
    Vue.use(VueRouter);
    
    const routes = [
      { path: '/', component: Home },
      { path: '/product/:id', component: ProductDetail },
      { path: '/cart', component: Cart },
      { path: '/login', component: Login },
      { path: '/register', component: Register },
    ];
    
    const router = new VueRouter({
      mode: 'history',
      routes,
    });
    
    export default router;
    
  3. Update src/main.js to use the router:

    import Vue from 'vue';
    import App from './App.vue';
    import router from './router';
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      render: h => h(App),
    }).$mount('#app');
    

Step 3: Creating Components

  1. Create ProductList.vue component:

    <template>
      <div class="product-list">
        <ProductItem v-for="product in products" :key="product.id" :product="product" />
      </div>
    </template>
    
    <script>
    import ProductItem from './ProductItem.vue';
    
    export default {
      components: { ProductItem },
      data() {
        return {
          products: [],
        };
      },
      created() {
        // Fetch products from API
        fetch('https://api.example.com/products')
          .then(response => response.json())
          .then(data => {
            this.products = data;
          });
      },
    };
    </script>
    
    <style scoped>
    .product-list {
      display: flex;
      flex-wrap: wrap;
    }
    </style>
    
  2. Create ProductItem.vue component:

    <template>
      <div class="product-item">
        <img :src="product.image" alt="Product Image" />
        <h3>{{ product.name }}</h3>
        <p>{{ product.price | currency }}</p>
        <router-link :to="`/product/${product.id}`">View Details</router-link>
      </div>
    </template>
    
    <script>
    export default {
      props: ['product'],
    };
    </script>
    
    <style scoped>
    .product-item {
      border: 1px solid #ccc;
      padding: 16px;
      margin: 16px;
      text-align: center;
    }
    </style>
    
  3. Create ShoppingCart.vue component:

    <template>
      <div class="shopping-cart">
        <h2>Shopping Cart</h2>
        <div v-if="cart.length === 0">Your cart is empty</div>
        <div v-else>
          <div v-for="item in cart" :key="item.id" class="cart-item">
            <img :src="item.image" alt="Product Image" />
            <h3>{{ item.name }}</h3>
            <p>{{ item.price | currency }}</p>
            <button @click="removeFromCart(item.id)">Remove</button>
          </div>
          <router-link to="/checkout">Proceed to Checkout</router-link>
        </div>
      </div>
    </template>
    
    <script>
    import { mapState, mapMutations } from 'vuex';
    
    export default {
      computed: {
        ...mapState(['cart']),
      },
      methods: {
        ...mapMutations(['removeFromCart']),
      },
    };
    </script>
    
    <style scoped>
    .shopping-cart {
      padding: 16px;
    }
    .cart-item {
      display: flex;
      align-items: center;
      margin-bottom: 16px;
    }
    .cart-item img {
      width: 100px;
      height: 100px;
      margin-right: 16px;
    }
    </style>
    
  4. Create Checkout.vue component:

    <template>
      <div class="checkout">
        <h2>Checkout</h2>
        <form @submit.prevent="submitOrder">
          <div>
            <label for="name">Name:</label>
            <input type="text" id="name" v-model="name" required />
          </div>
          <div>
            <label for="address">Address:</label>
            <input type="text" id="address" v-model="address" required />
          </div>
          <button type="submit">Place Order</button>
        </form>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          name: '',
          address: '',
        };
      },
      methods: {
        submitOrder() {
          // Handle order submission
          const order = {
            name: this.name,
            address: this.address,
            items: this.$store.state.cart,
          };
          fetch('https://api.example.com/orders', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify(order),
          })
            .then(response => response.json())
            .then(data => {
              alert('Order placed successfully!');
              this.$store.commit('clearCart');
              this.$router.push('/');
            });
        },
      },
    };
    </script>
    
    <style scoped>
    .checkout {
      padding: 16px;
    }
    form div {
      margin-bottom: 16px;
    }
    </style>
    

Step 4: Setting Up Vuex Store

  1. Install Vuex:

    npm install vuex
    
  2. Create the Vuex store (src/store/index.js):

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
        cart: [],
      },
      mutations: {
        addToCart(state, product) {
          state.cart.push(product);
        },
        removeFromCart(state, productId) {
          state.cart = state.cart.filter(item => item.id !== productId);
        },
        clearCart(state) {
          state.cart = [];
        },
      },
    });
    
  3. Update src/main.js to use the store:

    import Vue from 'vue';
    import App from './App.vue';
    import router from './router';
    import store from './store';
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      store,
      render: h => h(App),
    }).$mount('#app');
    

Step 5: Implementing User Authentication

  1. Create Login.vue component:

    <template>
      <div class="login">
        <h2>Login</h2>
        <form @submit.prevent="login">
          <div>
            <label for="email">Email:</label>
            <input type="email" id="email" v-model="email" required />
          </div>
          <div>
            <label for="password">Password:</label>
            <input type="password" id="password" v-model="password" required />
          </div>
          <button type="submit">Login</button>
        </form>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          email: '',
          password: '',
        };
      },
      methods: {
        login() {
          // Handle user login
          const credentials = {
            email: this.email,
            password: this.password,
          };
          fetch('https://api.example.com/login', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify(credentials),
          })
            .then(response => response.json())
            .then(data => {
              if (data.token) {
                localStorage.setItem('token', data.token);
                this.$router.push('/');
              } else {
                alert('Invalid credentials');
              }
            });
        },
      },
    };
    </script>
    
    <style scoped>
    .login {
      padding: 16px;
    }
    form div {
      margin-bottom: 16px;
    }
    </style>
    
  2. Create Register.vue component:

    <template>
      <div class="register">
        <h2>Register</h2>
        <form @submit.prevent="register">
          <div>
            <label for="email">Email:</label>
            <input type="email" id="email" v-model="email" required />
          </div>
          <div>
            <label for="password">Password:</label>
            <input type="password" id="password" v-model="password" required />
          </div>
          <button type="submit">Register</button>
        </form>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          email: '',
          password: '',
        };
      },
      methods: {
        register() {
          // Handle user registration
          const user = {
            email: this.email,
            password: this.password,
          };
          fetch('https://api.example.com/register', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify(user),
          })
            .then(response => response.json())
            .then(data => {
              if (data.id) {
                alert('Registration successful');
                this.$router.push('/login');
              } else {
                alert('Registration failed');
              }
            });
        },
      },
    };
    </script>
    
    <style scoped>
    .register {
      padding: 16px;
    }
    form div {
      margin-bottom: 16px;
    }
    </style>
    

Step 6: Deploying the Application

  1. Build the application for production:

    npm run build
    
  2. Deploy the application to a hosting service (e.g., Netlify, Vercel, etc.):

    • Follow the hosting service's instructions to deploy the built application.

Conclusion

In this project, we built a complete e-commerce website using Vue.js. We covered various aspects such as setting up the project, creating components, managing state with Vuex, handling user authentication, and deploying the application. This project should give you a solid understanding of how to build and deploy a real-world Vue.js application.

© Copyright 2024. All rights reserved