Vue

by luka kupunia

HTML

<div id="app">
    <ul>
      <li v-for="item in items" :key="item.id">
        <img :src="item.image" alt="" />
        <h3>{{ item.name }}</h3>
        <h4>price: {{ item.price }}$</h4>
        <button v-if="!item.isAdded" @click="addToCart(item.id)">
          Add to cart
        </button>
        <button v-else-if="item.isAdded" @click="removeFromCart(item.id)">
          Remove from cart
        </button>
      </li>
    </ul>
    <div class="basket">
      <div class="basket-item" v-for="item in basketItems" :key="item.id">
        <img :src="item.image" alt="" />
        <h3>{{ item.name }}</h3>
        <h4>price: {{ item.price }}$</h4>
        <div class="add-container">
          <button>-</button>
          <h2 class="sum">{{ item.quantity }}</h2>
          <button @click="addOneItem(item.id)">+</button>
        </div>
      </div>
    </div>
  </div>

CSS

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* text-align: center; */
  color: #2c3e50;
}
ul {
  display: flex;
}
ul li {
  margin: 20px 30px;
  border: 1px solid #eee;
  border-radius: 30px;
  list-style: none;
  text-align: center;
  padding: 20px;
  width: 20%;
  user-select: none;
}
ul li img {
  width: 100%;
  border-radius: 20px;
}
ul li button {
  width: 100%;
  background: #eee;
  border: none;
  padding: 15px;
  border-radius: 20px;
  font-weight: bold;
  cursor: pointer;
  outline: none;
  transition: 0.6s;
  color: inherit;
}
ul li button:hover {
  background: #cccbcb;
}
.basket {
  display: flex;
  flex-wrap: wrap;
  padding-left: 30px;
}
.basket .basket-item {
  width: 100%;
  display: flex;
  align-items: center;
  padding: 10px;
  border-radius: 15px;
  border: 1px solid #eee;
  margin-bottom: 10px;
}
.basket .basket-item img {
  width: 100px;
  margin-right: 15px;
  border-radius: 10px;
}
.basket .basket-item h3 {
  margin-right: 15px;
}
.add-container {
  display: flex;
  margin-left: 45px;
  align-items: center;
}
.add-container button {
  width: 45px;
  height: 45px;
  background: #eee;
  border: none;
  transition: 0.6s;
  border-radius: 50%;
  font-size: 24px;
  margin: 0 15px;
  cursor: pointer;
  outline: none;
}
.add-container button:hover {
  background: #cccbcb;
}

Vue

new Vue({
  el: "#app",
  data() {
    return {
      items: [
        {
          id: 1,
          name: "Nike Air Max 270",
          price: 160,
          image:
            "https://static.nike.com/a/images/f_auto/q_auto/t_PDP_864_v1/40911b96-5c18-4d59-b9a0-5e6743f58fb8/air-max-270-eng-shoe-bfmrw4.jpg",
          isAdded: false
        },
        {
          id: 2,
          name: "Nike Air Max 270 React",
          price: 170,
          image:
            "https://static.nike.com/a/images/f_auto/q_auto/t_PDP_864_v1/c0bd73b0-8077-4f97-990b-2697ada65d16/air-max-270-react-shoe-JvxxVM.jpg",
          isAdded: false
        },
        {
          id: 3,
          name: "Nike Air Max 270 react",
          price: 200,
          image:
            "https://static.nike.com/a/images/f_auto/q_auto/t_PDP_864_v1/1faa2d4a-36d3-4521-a924-e75bfa055341/air-max-270-react-shoe-WVPc8L.jpg",
          isAdded: false
        }
      ],
      basketItems: []
    };
  },
  methods: {
    addToCart(id) {
      const element = this.items.find(a => {
        if (a.id === id) {
          a.isAdded = !a.isAdded;
          a.quantity = 1;
        }
        return a.id === id;
      });
      this.basketItems.push(element);
    },
    removeFromCart(id) {
      this.basketItems.filter((a, b) => {
        if (a.id === id) {
          a.isAdded = !a.isAdded;
          return this.basketItems.splice(b, 1);
        }
      });
    },
    addOneItem(id) {
      return this.basketItems.filter(a => {
        if (a.id === id) {
          a.quantity++;
        }
      });
    }
  },
  mounted() {},
  computed: {}
})