Browse Source

Step 11 tabs.

Frederic G. MARAND 4 years ago
parent
commit
bf07c4dc0d
3 changed files with 206 additions and 167 deletions
  1. 5 0
      .idea/codeStyles/codeStyleConfig.xml
  2. 197 163
      main.js
  3. 4 4
      package.json

+ 5 - 0
.idea/codeStyles/codeStyleConfig.xml

@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>

+ 197 - 163
main.js

@@ -45,7 +45,20 @@ const productTemplate = `<div class="product">
         <button v-on:click="removeFromCart">Remove</button>
       </div>
 
-    <div>
+    <product-tabs :reviews="reviews"></product-tabs>
+  </div>
+`;
+
+const tabsTemplate = `
+  <div>
+    <span class="tab"
+          :class="{ activeTab: selectedTab == tab }"
+          v-for="(tab, index) in tabs" :key="index"
+          @click="selectedTab = tab">
+          {{ tab }}
+    </span>
+
+    <div v-show="selectedTab === 'Reviews'">
       <h2>Reviews</h2>
       <p v-if="!reviews.length">There are no reviews yet.</p>
       <ul>
@@ -56,191 +69,212 @@ const productTemplate = `<div class="product">
           <p>Review: {{ review.review }}</p>
         </li>
       </ul>
+    </div>    
+
+    <product-review v-show="selectedTab === 'Make a Review'" ></product-review>
   </div>
-    <product-review @review-submitted="addReview"></product-review>
-    </div>
 `;
 
+let eventBus = new Vue();
+
 Vue.component("product-details", {
-    props: {
-        details: {
-            type: Array,
-            required: true,
-        },
+  props: {
+    details: {
+      type: Array,
+      required: true,
     },
-    template: detailsTemplate,
+  },
+  template: detailsTemplate,
 });
 
 Vue.component("product-review", {
-    template: `
-      <form class="review-form" @submit.prevent="onSubmit">
-        <p v-if="errors.length">
-          <b>Please correct the following errror(s):</b>
-        <ul>
-          <li v-for="error in errors">{{ error }}</li>
-        </ul>
-        </p>
-
-        <p>
-          <label for="name">Name:</label>
-          <input id="name" v-model="name">
-        </p>
-        <p>
-          <label for="review">Review:</label>
-          <textarea id="review" v-model="review"></textarea>
-        </p>
-
-        <label for="rating">Rating:</label>
-        <select id="rating" v-model.number="rating">
-          <option>5</option>
-          <option>4</option>
-          <option>3</option>
-          <option>2</option>
-          <option>1</option>
-        </select>
-
-        <p>Would you recommend this product?</p>
-        <div>
-          <label for="reco-no">No</label> <input type="radio" v-model="recommend" id="reco-no" value="no">
-          <label for="reco-maybe">Maybe</label><input type="radio" v-model="recommend" id="reco-maybe" value="maybe">
-          <label for="reco-yes">Yes</label> <input type="radio" v-model="recommend" id="reco-yes" value="yes">
-        </div>
-
-        <p>
-          <input type="submit" value="Submit">
-        </p>
-      </form>
-    `,
-    data() {
-        return {
-            name: null,
-            recommend: null,
-            review: null,
-            rating: null,
-            errors: [],
-        }
-    },
-    methods: {
-        onSubmit(evt) {
-            this.errors = [];
-            if (this.name && this.review && this.rating && this.recommend) {
-                const productReview = {
-                    name: this.name,
-                    rating: this.rating,
-                    recommend: this.recommend,
-                    review: this.review,
-                };
-                this.$emit("review-submitted", productReview);
-                this.name = null;
-                this.rating = null;
-                this.recommend = null;
-                this.review = null;
-            } else {
-                for (const field of ["name", "rating", "recommend", "review"]) {
-                    if (!this[field]) {
-                        this.errors.push(`${field} required`);
-                    }
-                }
-            }
+  template: `
+    <form class="review-form" @submit.prevent="onSubmit">
+      <p v-if="errors.length">
+        <b>Please correct the following errror(s):</b>
+      <ul>
+        <li v-for="error in errors">{{ error }}</li>
+      </ul>
+      </p>
+
+      <p>
+        <label for="name">Name:</label>
+        <input id="name" v-model="name">
+      </p>
+      <p>
+        <label for="review">Review:</label>
+        <textarea id="review" v-model="review"></textarea>
+      </p>
+
+      <label for="rating">Rating:</label>
+      <select id="rating" v-model.number="rating">
+        <option>5</option>
+        <option>4</option>
+        <option>3</option>
+        <option>2</option>
+        <option>1</option>
+      </select>
+
+      <p>Would you recommend this product?</p>
+      <div>
+        <label for="reco-no">No</label> <input type="radio" v-model="recommend" id="reco-no" value="no">
+        <label for="reco-maybe">Maybe</label><input type="radio" v-model="recommend" id="reco-maybe" value="maybe">
+        <label for="reco-yes">Yes</label> <input type="radio" v-model="recommend" id="reco-yes" value="yes">
+      </div>
+
+      <p>
+        <input type="submit" value="Submit">
+      </p>
+    </form>
+  `,
+  data() {
+    return {
+      name: null,
+      recommend: null,
+      review: null,
+      rating: null,
+      errors: [],
+    }
+  },
+  methods: {
+    onSubmit(evt) {
+      this.errors = [];
+      if (this.name && this.review && this.rating && this.recommend) {
+        const productReview = {
+          name: this.name,
+          rating: this.rating,
+          recommend: this.recommend,
+          review: this.review,
+        };
+        eventBus.$emit("review-submitted", productReview);
+        this.name = null;
+        this.rating = null;
+        this.recommend = null;
+        this.review = null;
+      } else {
+        for (const field of ["name", "rating", "recommend", "review"]) {
+          if (!this[field]) {
+            this.errors.push(`${field} required`);
+          }
         }
+      }
     }
+  }
+});
+
+Vue.component("product-tabs", {
+  props: {
+    reviews: {
+      type: Array,
+      required: true,
+    }
+  },
+  template: tabsTemplate,
+  data() {
+    return {
+      selectedTab: "Reviews",
+      tabs: ["Reviews", "Make a Review"],
+    }
+  }
 });
 
 Vue.component("product", {
-    props: {
-        isPremium: {
-            type: Boolean,
-            required: true,
-        }
+  props: {
+    isPremium: {
+      type: Boolean,
+      required: true,
+    }
+  },
+  template: productTemplate,
+  // Computer properties are cached until dependencies change.
+  // => cheaper than methods.
+  computed: {
+    image() {
+      const image = this.variants[this.selectedVariant].variantImage;
+      return image;
     },
-    template: productTemplate,
-    // Computer properties are cached until dependencies change.
-    // => cheaper than methods.
-    computed: {
-        image() {
-            const image = this.variants[this.selectedVariant].variantImage;
-            return image;
-        },
-        inStock() {
-            return this.variants[this.selectedVariant].variantQuantity > 0;
-        },
-        shipping() {
-            if (this.isPremium) {
-                return "Free";
-            }
-            return "2.99 €";
-        },
-        title() {
-            return [this.brand, this.product].join(' ');
-        }
+    inStock() {
+      return this.variants[this.selectedVariant].variantQuantity > 0;
     },
-    data() {
-        return {
-            brand: "Vue Mastery",
-            description: "Chaussettes montantes",
-            details: [
-                "80% cotton",
-                "20% polyester",
-                "Gender-neutral",
-            ],
-            inventory: 15,
-            link: "https://www.google.com/search?q=vuejs+socks",
-            product: "Socks",
-            reviews: [],
-            selectedVariant: 0,
-            sizes: [34, 36, 38, 40, 42, 44, 46],
-            variants: [
-                {
-                    variantId: 2234,
-                    variantColor: "green",
-                    variantImage: "./assets/img/vmSocks-green-onWhite.jpg",
-                    variantQuantity: 10,
-                },
-                {
-                    variantId: 2235,
-                    variantColor: "blue",
-                    variantImage: "./assets/img/vmSocks-blue-onWhite.png",
-                    variantQuantity: 0,
-                },
-            ]
-        }
+    shipping() {
+      if (this.isPremium) {
+        return "Free";
+      }
+      return "2.99 €";
     },
-    methods: {
-        addToCart() {
-            this.variants[this.selectedVariant].variantQuantity--;
-            this.$emit("add-to-cart", this.variants[this.selectedVariant].variantId);
-        },
-        addReview(productReview) {
-            this.reviews.push(productReview);
+    title() {
+      return [this.brand, this.product].join(' ');
+    }
+  },
+  data() {
+    return {
+      brand: "Vue Mastery",
+      description: "Chaussettes montantes",
+      details: [
+        "80% cotton",
+        "20% polyester",
+        "Gender-neutral",
+      ],
+      inventory: 15,
+      link: "https://www.google.com/search?q=vuejs+socks",
+      product: "Socks",
+      reviews: [],
+      selectedVariant: 0,
+      sizes: [34, 36, 38, 40, 42, 44, 46],
+      variants: [
+        {
+          variantId: 2234,
+          variantColor: "green",
+          variantImage: "./assets/img/vmSocks-green-onWhite.jpg",
+          variantQuantity: 10,
         },
-        removeFromCart() {
-            this.variants[this.selectedVariant].variantQuantity++;
-            this.$emit("remove-from-cart", this.variants[this.selectedVariant].variantId);
+        {
+          variantId: 2235,
+          variantColor: "blue",
+          variantImage: "./assets/img/vmSocks-blue-onWhite.png",
+          variantQuantity: 0,
         },
-        updateImage(index) {
-            this.selectedVariant = index;
-        }
+      ]
+    }
+  },
+  methods: {
+    addToCart() {
+      this.variants[this.selectedVariant].variantQuantity--;
+      this.$emit("add-to-cart", this.variants[this.selectedVariant].variantId);
     },
+    removeFromCart() {
+      this.variants[this.selectedVariant].variantQuantity++;
+      this.$emit("remove-from-cart", this.variants[this.selectedVariant].variantId);
+    },
+    updateImage(index) {
+      this.selectedVariant = index;
+    }
+  },
+  mounted() {
+    eventBus.$on('review-submitted', productReview => {
+      this.reviews.push(productReview);
+    });
+  }
 });
 
 const app = new Vue({
-    el: "#app",
-    data: {
-        cart: [],
-        isPremium: false,
+  el: "#app",
+  data: {
+    cart: [],
+    isPremium: false,
+  },
+  methods: {
+    removeItem(id) {
+      console.log("removeItem", id);
+      const index = this.cart.indexOf(id);
+      if (index > -1) {
+        this.cart.splice(index, 1);
+      }
     },
-    methods: {
-        removeItem(id) {
-            console.log("removeItem", id);
-            const index = this.cart.indexOf(id);
-            if (index > -1) {
-                this.cart.splice(index, 1);
-            }
-        },
-        updateCart(id) {
-            console.log("updateCart", id);
-            this.cart.push(id);
-        }
+    updateCart(id) {
+      console.log("updateCart", id);
+      this.cart.push(id);
     }
+  }
 });
 

+ 4 - 4
package.json

@@ -3,6 +3,9 @@
   "dependencies": {
     "vue": "^2.6.10"
   },
+  "devDependencies": {
+    "serve": "^11.2.0"
+  },
   "license": "MIT",
   "main": "main.js",
   "name": "js__vue_mastery",
@@ -10,8 +13,5 @@
   "scripts": {
     "serve": "npx serve"
   },
-  "version": "1.0.0",
-  "devDependencies": {
-    "serve": "^11.2.0"
-  }
+  "version": "1.0.0"
 }