|
@@ -44,6 +44,19 @@ const productTemplate = `<div class="product">
|
|
|
>Add to cart</button>
|
|
|
<button v-on:click="removeFromCart">Remove</button>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <h2>Reviews</h2>
|
|
|
+ <p v-if="!reviews.length">There are no reviews yet.</p>
|
|
|
+ <ul>
|
|
|
+ <li v-for="review in reviews">
|
|
|
+ <p>{{ review.name }}</p>
|
|
|
+ <p>{{ review.rating }}</p>
|
|
|
+ <p>{{ review.review }}</p>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <product-review @review-submitted="addReview"></product-review>
|
|
|
</div>
|
|
|
`;
|
|
|
|
|
@@ -57,6 +70,71 @@ Vue.component("product-details", {
|
|
|
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>
|
|
|
+ <input type="submit" value="Submit">
|
|
|
+ </p>
|
|
|
+ </form>
|
|
|
+ `,
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ name: null,
|
|
|
+ review: null,
|
|
|
+ rating: null,
|
|
|
+ errors: [],
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onSubmit(evt) {
|
|
|
+ this.errors = [];
|
|
|
+ if (this.name && this.review && this.rating) {
|
|
|
+ const productReview = {
|
|
|
+ name: this.name,
|
|
|
+ rating: this.rating,
|
|
|
+ review: this.review,
|
|
|
+ };
|
|
|
+ this.$emit("review-submitted", productReview);
|
|
|
+ this.name = null;
|
|
|
+ this.rating = null;
|
|
|
+ this.review = null;
|
|
|
+ } else {
|
|
|
+ for (const field of ["name", "rating", "review"]) {
|
|
|
+ if (!this[field]) {
|
|
|
+ this.errors.push(`${field} required`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
Vue.component("product", {
|
|
|
props: {
|
|
|
isPremium: {
|
|
@@ -97,6 +175,7 @@ Vue.component("product", {
|
|
|
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: [
|
|
@@ -120,6 +199,9 @@ Vue.component("product", {
|
|
|
this.variants[this.selectedVariant].variantQuantity--;
|
|
|
this.$emit("add-to-cart", this.variants[this.selectedVariant].variantId);
|
|
|
},
|
|
|
+ addReview(productReview) {
|
|
|
+ this.reviews.push(productReview);
|
|
|
+ },
|
|
|
removeFromCart() {
|
|
|
this.variants[this.selectedVariant].variantQuantity++;
|
|
|
this.$emit("remove-from-cart", this.variants[this.selectedVariant].variantId);
|