Shop Item with Vue

Simple sandbox project with Vue.js. Add drink to your cart and see how many items are left in stock.

Author

Davis

Html

<div id="app" class="container">
    <div class="cart">
      <p class="cart-text" v-if="cartStatus()">You have {{ itemsInCart }} bottles in your cart</p>
      <p class="cart-text_empty" v-else>Your cart is empty</p>
      <button v-if="itemsInCart > 0" class="button-cart_primary">Go to checkout</button>
      <button @click="emptyCart" v-if="itemsInCart > 0" class="button-cart_secondary">Empty cart</button>
    </div>
    <div class="item">
      <img src="https://images.unsplash.com/photo-1506277789875-529f12691361?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=d708b98eaaa2379bb6d3c8d40240ce5c&auto=format&fit=crop&w=1296&q=60" alt="product-image" class="item-image">
      <div class="item-section">
        <div>
          <h3 class="item-title">Confused Duck drink</h3>
          <p class="item-meta">530 ml</p>
          <p class="item-meta">{{ itemsInStock }} items left in stock</p>
        </div>
        <span class="item-price">€ 4.99</span>
      </div>
      <p class="item-description">Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe vero quos non veniam quaerat . Soluta, repudiandae incidunt! Ullam, autem tenetur!</p>
      <div class="quantity">
        <button class="button-quantity" @click="quantity--" :disabled="quantity < 1">-</button>
        <input type="number" class="quantity-input" v-model="quantity">
        <button class="button-quantity" @click="quantity++" :disabled="quantity >= itemsInStock">+</button>
      </div>
      <button class="button-order" @click="addItemToCart" :disabled="itemsInStock == 0 || quantity == 0 || quantity > itemsInStock">Add to cart</button>
    </div>
  </div>
  <script src="script.js"></script>

Css

:root {
  --color-text: #6C727D;
  --color-main: #FF3A52;
  --color-bg: #F2F4F5;
}

body {
  margin: 0;
  padding: 0;
  font-family: 'Montserrat', sans-serif;
  background: #143040;
}

.container {
  width: 90%;
  max-width: 360px;
  margin: 0 auto;
  padding: 40px 0;
}

.cart {
  margin-bottom: 24px;
  background: var(--color-bg);
  padding: 16px;
  border-radius: 3px;
}

.cart-text {
  margin: 0 0 12px;
  color: var(--color-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
}

.cart-text_empty {
  margin: 0;
  color: var(--color-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
}

.item {
  background: var(--color-bg);
  padding: 16px 16px 48px;
  border-radius: 3px;
}

.item-image {
  width: 100%;
  height: auto;
  display: block;
  margin-bottom: 16px;
}

.item-section {
  margin-bottom: 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid rgba(108, 114, 125, .3);
  padding-bottom: 16px;
}

.item-title {
  margin: 0 0 4px;
  font-size: 16px;
  font-weight: 600;
}

.item-meta {
  margin: 0;
  font-weight: 500;
  color: var(--color-text);
  font-size: 14px;
  opacity: .5;
}

.item-price {
  font-weight: 500;
  font-size: 24px;
  color: var(--color-main);
}

.item-description {
  margin: 0 0 16px;
  color: var(--color-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
}

.quantity-input::-webkit-inner-spin-button,
.quantity-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.quantity {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 32px;
}

.quantity-input {
  width: 36px;
  height: 36px;
  text-align: center;
  border-radius: 3px;
  border: 1px solid #929CAA;
  font-size: 16px;
  margin: 0 16px;
  color: var(--color-text);
}

.quantity-show {
  margin: 0 0 32px;
  color: var(--color-text);
  font-size: 14px;
  font-weight: 500;
  line-height: 21px;
}

.button-quantity {
  background: var(--color-bg);
  border: none;
  border-radius: 50%;
  font-size: 24px;
  padding: 7px 13px;
  cursor: pointer;
  color: var(--color-text);
  outline: none;
}

.button-quantity:disabled {
  opacity: .2;
}

.button-order {
  display: block;
  width: 100%;
  max-width: 200px;
  margin: 0 auto;
  background: var(--color-main);
  border: 1px solid var(--color-main);
  color: #FFF;
  border-radius: 24px;
  padding: 12px 0;
  font-size: 16px;
  box-shadow: 0 2px 4px rgba(0,0,0,.18);
  text-shadow: 0 1px 2px rgba(0,0,0,.2);
  cursor: pointer;
  outline: none;
}

.button-order:disabled {
  opacity: .4;
  cursor: not-allowed;
}

.button-cart_primary {
  background: var(--color-main);
  color: #FFF;
  border: 1px solid var(--color-main);;
  border-radius: 16px;
  font-size: 14px;
  padding: 6px 12px;
  cursor: pointer;
  outline: none;
  box-shadow: 0 2px 4px rgba(0,0,0,.18);
  text-shadow: 0 1px 2px rgba(0,0,0,.2);
}

.button-cart_secondary {
  color: var(--color-text);
  background: transparent;
  border: none;
  font-size: 13px;
  cursor: pointer;
  outline: none;
  padding: 7px 12px;
  letter-spacing: .5px;
  opacity: .8;
}

.button-cart_secondary:hover {
  background: #E5E7EA;
  border-radius: 16px;
}

@keyframes loading {
  0% {
    flex-grow: 0;
    opacity: 0;
  }
  100% {
    flex-grow: 4;
    opacity: 1;
  }
}

Javascript

new Vue({
  el: '#app',
  data: {
    itemsInCart: 0,
    itemsInStock: 5,
    quantity: 1
  },
  methods: {
    addItemToCart() {
      if (this.itemsInStock > 0) {
        this.quantity = parseInt(this.quantity)
        this.itemsInCart += this.quantity
        this.itemsInStock -= this.quantity
        this.quantity = 0
      }
    },
    cartStatus() {
      if (this.itemsInCart > 0) {
        return true
      } else {
        return false
      }
    },
    emptyCart() {
      this.itemsInStock = this.itemsInStock + this.itemsInCart
      this.itemsInCart = 0
    }
  }

})

Demo

See the Pen Shop Item with Vue by Davis (@davisnorde) on CodePen.