浏览代码

vuex 적용, state, action, mutations, computed, ...mapGetters

kiboky 5 年之前
父节点
当前提交
c2e9af7832
共有 4 个文件被更改,包括 271 次插入2 次删除
  1. 5 1
      client/components/Navbar.vue
  2. 204 0
      client/pages/cart.vue
  3. 5 1
      client/pages/products/_id.vue
  4. 57 0
      client/store/index.js

+ 5 - 1
client/components/Navbar.vue

@@ -111,7 +111,7 @@
                 <span aria-hidden="true" class="nav-line-1"></span>
                 <span aria-hidden="true" class="nav-line-2">Cart</span>
                 <span class="nav-cart-icon nav-sprite"></span>
-                <span aria-hidden="true" class="nav-cart-count nav-cart-0">0</span>
+                <span aria-hidden="true" class="nav-cart-count nav-cart-0">{{ getCartLength }}</span>
               </nuxt-link>
             </div>
           </div>
@@ -125,10 +125,14 @@
 </template>
 
 <script>
+import { mapGetters } from  'vuex'
 import Search from '~/components/Search'
 export default {
   components: {
     Search
+  },
+  computed: {
+    ...mapGetters(['getCartLength'])
   }
 }
 </script>

+ 204 - 0
client/pages/cart.vue

@@ -0,0 +1,204 @@
+<template>
+  <!--MAIN-->
+  <main>
+    <!--SHOPPING CART-->
+    <div class="shopping-cart mt-3">
+      <div class="container-fluid c-section">
+        <div class="row">
+          <div class="col-lg-9 col-md-8 col-sm-7">
+            <div class="c-section a-spacing-top-base">
+              <div class="a-row sc-cart-header sc-compact-bottom">
+                <h2>Shopping Cart</h2>
+              </div>
+              <form action="#" method="post">
+                <div class="sc-list-head">
+                  <div class="text-right a-spacing-top-micro">
+                    <span class="a-color-secondary">Price</span>
+                  </div>
+                </div>
+                <!-- List of the item -->
+                <div v-for="product in getCart" :key="product._id" class="sc-list-body">
+                  <div class="sc-list-item-border">
+                    <div class="a-row a-spacing-top-base a-spacing-base">
+                      <div class="row">
+                        <!-- Product's Image -->
+                        <div class="col-sm-2 col-2">
+                          <a href="#" class="a-link-normal">
+                            <img :src="product.photo" class="img-fluid w-100" />
+                          </a>
+                        </div>
+                        <div class="col-sm-8 col-8">
+                          <!-- Product's Title -->
+                          <div class="a-spacing-mini">
+                            <a
+                              href="#"
+                              class="a-link-normal a-size-medium a-text-bold"
+                            >{{ product.title }}</a>
+                            <!-- Product's Owner name -->
+                            <span class="a-size-base sc-product-creator">{{ product.owner.name }}</span>
+                          </div>
+                          <div>
+                            <span
+                              class="a-size-small a-color-secondary sc-product-binding"
+                            >Paperback</span>
+                          </div>
+                          <div>
+                            <span
+                              class="a-size-small a-color-success sc-product-availability"
+                            >In Stock</span>
+                          </div>
+                          <div class="a-checkbox a-align-top a-size-small a-spacing-top-micro">
+                            <label>
+                              <input type="checkbox" name value />
+                              <span class="a-checkbox-label">
+                                This is a gift
+                                <span class="a-size-small">
+                                  <a href="#">
+                                    <span class="a-size-small">Learn More</span>
+                                  </a>
+                                </span>
+                              </span>
+                            </label>
+                          </div>
+                          <div class="sc-action-links">
+                            <select>
+                              <option>Qty: &nbsp;1</option>
+                            </select>
+                            &nbsp;&nbsp;
+                            <span>|</span>
+                            &nbsp;
+                            <!-- Delete button -->
+                            <span class="a-size-small">
+                              <a href="#">Delete</a>
+                            </span>
+                            &nbsp;
+                            &nbsp;
+                          </div>
+                        </div>
+                        <div class="col-sm-2 col-2 tr sm-txt-r">
+                          <!-- Product's Price -->
+                          <p class="a-spacing-small">
+                            <span
+                              class="a-size-medium a-color-price sc-price sc-white-space-nowrap sc-product-price sc-price-sign a-text-bold"
+                            >${{ product.price * product.quantity }}</span>
+                          </p>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <!-- List of the item -->
+
+                <div class="text-right">
+                  <!-- Cart Subtotal -->
+                  <p class="a-spacing-none a-spacing-top-mini">
+                    <span class="a-size-medium">Subtotal ({{ getCartLength }} item)</span>
+                    <span class="a-color-price a-text-bold">
+                      <!-- Cart Total Price -->
+                      <span class="a-size-medium a-color-price">${{ getCartTotalPrice }}</span>
+                    </span>
+                  </p>
+                </div>
+              </form>
+            </div>
+          </div>
+          <div class="col-lg-3 col-md-4 col-sm-5">
+            <div class="a-box-group" style="margin-bottom: 14px;">
+              <div class="a-box a-color-alternate-background">
+                <div class="a-box-inner">
+                  <div class="a-spacing-mini">
+                    <p class="a-spacing-none a-spacing-top-none">
+                      <!-- Cart Subtotal -->
+                      <span class="a-size-medium">
+                        <span>Subtotal ({{ getCartLength }} item):</span>
+                        <span class="a-color-price a-text-bold">
+                          <!-- Cart Total Price  -->
+                          <span class="a-size-medium a-color-price">${{ getCartTotalPrice }}</span>
+                        </span>
+                      </span>
+                    </p>
+                  </div>
+                  <div class="a-spacing-base mt-1">
+                    <input type="checkbox" name="checkbox" />
+                    <span class="a-label a-checkbox-label">This order contains a gift</span>
+                  </div>
+                  <div>
+                    <span class="a-spacing-small a-button-primary a-button-icon">
+                      <span class="a-button-inner">
+                        <a href="#" class="a-button-text">Proceed to checkout</a>
+                      </span>
+                    </span>
+                  </div>
+                </div>
+              </div>
+            </div>
+
+            <!-- Recently Viewed -->
+            <div class="a-spacing-large">
+              <div class="a-box">
+                <div class="a-box-inner">
+                  <h5 class="a-spacing-base">Your recently viewed items</h5>
+                  <div class="a-spacing-micro">
+                    <ul class="a-unordered-list recently-viewed">
+                      <li class="a-spacing-medium" v-for="i in 4" :key="i">
+                        <span class="a-list-item">
+                          <div class="row">
+                            <div class="col-md-4 col-sm-3 col-3 pl-0">
+                              <a href="#">
+                                <img src="img/cartRecent4.png" class />
+                              </a>
+                            </div>
+                            <div class="col-md-8 col-sm-9 col-9">
+                              <a href="#" class="a-link-normal">The Everything Store:…</a>
+                              <div class="a-size-small">
+                                <a href="#" class="a-size-small a-link-child">Brad Stone</a>
+                              </div>
+                              <div class="a-icon-row a-spacing-none">
+                                <a href="#">
+                                  <i class="fas fa-star"></i>
+                                  <i class="fas fa-star"></i>
+                                  <i class="fas fa-star"></i>
+                                  <i class="fas fa-star"></i>
+                                  <i class="fas fa-star-half-alt"></i>
+                                </a>
+                                <a href="#">155</a>
+                              </div>
+                              <div class="a-size-small">
+                                <span class="a-size-small a-color-secondary">Kindle Edition</span>
+                              </div>
+                              <div class="a-spacing-top-micro">
+                                <span
+                                  class="a-button-inspired a-spacing-top-none a-button-base a-button-small"
+                                >
+                                  <span class="a-button-inner">
+                                    <a href="#" class="a-button-text">See all buying options</a>
+                                  </span>
+                                </span>
+                              </div>
+                            </div>
+                          </div>
+                        </span>
+                      </li>
+                    </ul>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!--/SHOPPING CART-->
+  </main>
+  <!--/MAIN-->
+</template>
+
+<script>
+import { mapGetters } from  'vuex'
+export default {
+
+  computed: {
+    ...mapGetters(['getCart', 'getCartTotalPrice', 'getCartLength'])
+  }
+}
+</script>

+ 5 - 1
client/pages/products/_id.vue

@@ -258,7 +258,7 @@
                 </div>
 
                 <div class="a-section">
-                  <div class="a-button-stack">
+                  <div @click="addProductToCart(product)" class="a-button-stack">
                     <span class="a-spacing-small a-button-primary a-button-icon">
                       <span class="a-button-inner">
                         <i class="a-icon a-icon-cart"></i>
@@ -365,6 +365,7 @@
 
 
 <script>
+import { mapActions } from 'vuex'
 import StarRating from 'vue-star-rating'
 import ReviewSection from '~/components/ReviewSection'
 
@@ -389,6 +390,9 @@ export default {
     } catch (err) {
       console.log(err)
     }
+  },
+  methods: {
+    ...mapActions(['addProductToCart'])
   }
 }
 </script>

+ 57 - 0
client/store/index.js

@@ -0,0 +1,57 @@
+export const state = () => ({
+  cart: [],
+  cartLength: 0
+})
+
+export const actions = {
+  addProductToCart ({ state, commit }, product) {
+    const cartProduct = state.cart.find(prod => prod._id === product._id)
+
+    if (!cartProduct) {
+      commit('pushProductToCart', product)
+    } else {
+      commit('incrementProductQty', product)
+    }
+
+    commit('incrementCartLength')
+  }
+}
+
+export const mutations = {
+  pushProductToCart (state, product) {
+    product.quantity = 1
+    state.cart.push(product)
+  },
+
+  incrementProductQty (state, product) {
+    product.quantity++
+    let indexOfProduct = state.cart.indexOf(product)
+    state.cart.splice(indexOfProduct, 1, product)
+  },
+
+  incrementCartLength (state) {
+    state.cartLength = 0
+    if (state.cart.length > 0) {
+      state.cart.map(product => {
+        state.cartLength += product.quantity
+      })
+    }
+
+  }
+}
+
+export const getters = {
+  getCartLength (state) {
+    return state.cartLength
+  },
+  getCart (state) {
+    return state.cart
+  },
+  getCartTotalPrice (state) {
+    let total = 0
+    state.cart.map(product => {
+      total += product.price * product.quantity
+    })
+    return total
+  }
+}