Агаев Даниэл Сейранович 3 rokov pred
commit
d97f186e3c

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 8 - 0
.idea/2.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/2.iml" filepath="$PROJECT_DIR$/.idea/2.iml" />
+    </modules>
+  </component>
+</project>

+ 93 - 0
assets/css/style.css

@@ -0,0 +1,93 @@
+body {
+    font-family: tahoma;
+    color:#282828;
+    margin: 0px;
+}
+
+.nav-bar {
+    background: linear-gradient(-90deg, #84CF6A, #16C0B0);
+    height: 60px;
+    margin-bottom: 15px;
+}
+
+.product {
+    display: flex;
+    flex-flow: wrap;
+    padding: 1rem;
+}
+
+img {
+    border: 1px solid #d8d8d8;
+    width: 70%;
+    margin: 40px;
+    box-shadow: 0px .5px 1px #d8d8d8;
+}
+
+.product-image {
+    width: 80%;
+}
+
+.product-image,
+.product-info {
+    margin-top: 10px;
+    width: 50%;
+}
+
+.color-box {
+    width: 40px;
+    height: 40px;
+    margin-top: 5px;
+}
+
+.cart {
+    margin-right: 25px;
+    float: right;
+    border: 1px solid #d8d8d8;
+    padding: 5px 20px;
+}
+
+button {
+    margin-top: 30px;
+    border: none;
+    background-color: #1E95EA;
+    color: white;
+    height: 40px;
+    width: 100px;
+    font-size: 14px;
+}
+
+.disabledButton {
+    background-color: #d8d8d8;
+}
+
+.review-form {
+    width: 400px;
+    padding: 20px;
+    margin: 40px;
+    border: 1px solid #d8d8d8;
+}
+
+input {
+    width: 100%;
+    height: 25px;
+    margin-bottom: 20px;
+}
+
+textarea {
+    width: 100%;
+    height: 60px;
+}
+
+.tab {
+    margin-left: 20px;
+    cursor: pointer;
+}
+
+.activeTab {
+    color: #16C0B0;
+    text-decoration: underline;
+}
+
+.kill {
+    text-decoration: line-through
+}

BIN
assets/img/black.png


BIN
assets/img/pink.png


+ 301 - 0
assets/js/main.js

@@ -0,0 +1,301 @@
+
+let eventBus = new Vue(
+);
+
+
+
+
+
+
+Vue.component('product', {
+    props: {
+        premium: {
+            type: Boolean,
+            required: true
+        }
+    },
+
+    template: `
+	 <div class="product">
+        <div class="product-image">
+            <img :src="image" :alt="altText"/>
+        </div>
+
+        <div class="product-info">
+            <h1>{{ title }}</h1>
+      
+            <p v-if="inStock">In stock</p>
+            <p v-else>Out of Stock</p>
+           
+ <p>Shipping: {{ shipping }}</p>
+ 
+  <product-details></product-details>
+ 
+            <div
+                    class="color-box"
+                    v-for="(variant, index) in variants"
+                    :key="variant.variantId"
+                    :style="{ backgroundColor:variant.variantColor }"
+                    @mouseover="updateProduct(index)"
+            ></div>
+        </div>
+
+     
+        <button
+                @click="addToCart"
+                :disabled="!inStock"
+                :class="{ disabledButton: !inStock }"
+        >
+            Add to cart
+        </button>
+        
+            <button
+                @click="removeToCart"
+                :disabled="!inStock"
+                :class="{ disabledButton: !inStock }"
+        >
+            remove to cart
+        </button>
+
+
+<product-tabs :reviews="reviews"></product-tabs>
+
+  
+    </div>
+ `,
+    data() {
+        return {
+            product: "Socks",
+            reviews: [],
+            brand: 'Vue Mastery',
+            selectedVariant: 0,
+            altText: "A pair of socks",
+            details: ['80% cotton', '20% polyester', 'Gender-neutral'],
+            variants: [
+                {
+                    variantId: 2234,
+                    variantColor: 'green',
+                    variantImage: "./assets/vmSocks-green-onWhite.jpg",
+                    variantQuantity: 10
+                },
+                {
+                    variantId: 2235,
+                    variantColor: 'blue',
+                    variantImage: "./assets/vmSocks-blue-onWhite.jpg",
+                    variantQuantity: 0
+                }
+            ],
+            cart: 0
+        }
+    },
+
+    mounted() {
+        eventBus.$on('review-submitted', productReview => {
+            this.reviews.push(productReview)
+        })
+    },
+
+    methods: {
+        addToCart() {
+            this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
+
+        },
+
+        removeToCart() {
+            this.$emit('remove-to-cart', this.variants[this.selectedVariant].variantId);
+
+        },
+
+        updateProduct(index) {
+            this.selectedVariant = index;
+            console.log(index);
+        },
+    },
+    computed: {
+        title() {
+            return this.brand + ' ' + this.product;
+        },
+        image() {
+            return this.variants[this.selectedVariant].variantImage;
+        },
+        inStock() {
+            return this.variants[this.selectedVariant].variantQuantity
+        },
+        shipping() {
+            if (this.premium) {
+                return "Free";
+            } else {
+                return 2.99
+            }
+        }
+
+    }
+
+})
+
+Vue.component('product-details', {
+    data() {
+        return {
+            details: ['80% cotton', '20% polyester', 'Gender-neutral'],
+
+        }
+
+    },
+    template: `
+         <ul>
+                <li v-for="detail in details">{{ detail }}</li>
+            </ul>
+        `
+    ,
+});
+
+
+Vue.component('product-review', {
+    template: `
+
+ 
+  <form class="review-form" @submit.prevent="onSubmit"> 
+  
+  <p v-if="errors.length">
+ <b>Please correct the following error(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" placeholder="name">
+ </p>
+ <p>
+   <label for="name">Would you recommend this product?:</label>
+   <input id="name" v-model="radio" type="radio" value="yes" placeholder="no">
+   <input id="name" v-model="radio" type="radio" value="no" placeholder="yes">
+ </p>
+
+ <p>
+   <label for="review">Review:</label>
+   <textarea id="review" v-model="review"></textarea>
+ </p>
+
+ <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>
+
+ <p>
+   <input type="submit" value="Submit"> 
+ </p>
+ 
+ 
+
+ </form>
+
+ `,
+    data() {
+        return {
+            name: null,
+            review: null,
+            rating: null,
+            radio: null,
+                errors: []
+    }
+    },
+
+    methods: {
+        onSubmit() {
+            if(this.name && this.review && this.rating&& this.radio) {
+                let productReview = {
+                    name: this.name,
+                    review: this.review,
+                    rating: this.rating,
+                    radio: this.radio,
+
+                }
+                eventBus.$emit('review-submitted', productReview)
+
+                this.name = null
+                this.review = null
+                this.rating = null
+                this.radio = null
+            } else {
+                if(!this.name) this.errors.push("Name required.")
+                if(!this.review) this.errors.push("Review required.")
+                if(!this.rating) this.errors.push("Rating required.")
+                if(!this.radio) this.errors.push("Radio required.")
+            }
+
+        }
+    }
+
+})
+
+Vue.component('product-tabs', {
+    props: {
+        reviews: {
+            type: Array,
+            required: false
+        }
+    },
+    template: `
+ <div>   
+       <ul>
+         <span class="tab"
+               :class="{ activeTab: selectedTab === tab }"
+               v-for="(tab, index) in tabs"
+               @click="selectedTab = tab"
+         >{{ tab }}</span>
+       </ul>
+       <div v-show="selectedTab === 'Reviews'">
+         <p v-if="!reviews.length">There are no reviews yet.</p>
+         <ul>
+           <li v-for="review in reviews">
+           <p>{{ review.name }}</p>
+           <p>Rating: {{ review.rating }}</p>
+           <p>{{ review.review }}</p>
+           </li>
+         </ul>
+       </div>
+       <div v-show="selectedTab === 'Make a Review'">
+         <product-review></product-review>
+       </div>
+     </div>
+
+ `,
+    data() {
+        return {
+            tabs: ['Reviews', 'Make a Review'],
+            selectedTab: 'Reviews'  // устанавливается с помощью @click
+        }
+    },
+
+})
+
+
+
+let app = new Vue({
+    el: '#app',
+    data: {
+        premium: true,
+        cart: []
+    },
+    methods: {
+        updateCart(id) {
+            this.cart.push(id);
+        },
+        removeCart(id) {
+            let i = this.cart.indexOf(id);
+            this.cart.splice(i, 1);
+        }
+    }
+})
+
+
+
+

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 12014 - 0
assets/js/vue.js


BIN
assets/vmSocks-blue-onWhite.jpg


BIN
assets/vmSocks-green-onWhite.jpg


+ 29 - 0
index.html

@@ -0,0 +1,29 @@
+<!doctype html>
+<html lang="ru">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <script defer src="assets/js/vue.js"></script>
+    <script defer src="assets/js/main.js"></script>
+    <title>Product App</title>
+    <link rel="stylesheet" href="assets/css/style.css">
+</head>
+<body>
+
+
+<div id="app">
+    <div class="cart">
+        <p>Cart({{ cart.length }})</p>
+    </div>
+    <product @remove-to-cart="removeCart" :premium="premium" @add-to-cart="updateCart" ></product>
+
+
+
+</div>
+
+
+
+</body>
+</html>