diff --git a/coverage/clover.xml b/coverage/clover.xml index 94c6940..3a0cbe3 100644 --- a/coverage/clover.xml +++ b/coverage/clover.xml @@ -1,25 +1,82 @@ - - - + + + - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + - - - - + + + + + diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json index 1ac6bb0..49dcd5e 100644 --- a/coverage/coverage-final.json +++ b/coverage/coverage-final.json @@ -1,4 +1,11 @@ -{"/Users/viricel/Sites/fruit-project/src/components/Grid.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Grid.vue","statementMap":{"0":{"start":{"line":8,"column":0},"end":{"line":8,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":1},"f":{},"b":{}} -,"/Users/viricel/Sites/fruit-project/src/views/Fruit.vue": {"path":"/Users/viricel/Sites/fruit-project/src/views/Fruit.vue","statementMap":{"0":{"start":{"line":9,"column":0},"end":{"line":9,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0},"f":{},"b":{}} -,"/Users/viricel/Sites/fruit-project/src/views/Fruits.vue": {"path":"/Users/viricel/Sites/fruit-project/src/views/Fruits.vue","statementMap":{"0":{"start":{"line":9,"column":0},"end":{"line":9,"column":null}},"1":{"start":{"line":10,"column":0},"end":{"line":10,"column":null}},"2":{"start":{"line":19,"column":0},"end":{"line":19,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":0},"end":{"line":18,"column":null}},"loc":{"start":{"line":18,"column":0},"end":{"line":20,"column":null}}}},"branchMap":{},"s":{"0":1,"1":1,"2":0},"f":{"0":0},"b":{}} +{"/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue","statementMap":{"0":{"start":{"line":44,"column":0},"end":{"line":44,"column":null}},"1":{"start":{"line":50,"column":0},"end":{"line":50,"column":null}},"2":{"start":{"line":55,"column":0},"end":{"line":55,"column":null}},"3":{"start":{"line":59,"column":0},"end":{"line":59,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":49,"column":0},"end":{"line":49,"column":null}},"loc":{"start":{"line":49,"column":0},"end":{"line":53,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":54,"column":0},"end":{"line":54,"column":null}},"loc":{"start":{"line":54,"column":0},"end":{"line":56,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":58,"column":0},"end":{"line":58,"column":null}},"loc":{"start":{"line":58,"column":0},"end":{"line":60,"column":null}}}},"branchMap":{},"s":{"0":1,"1":0,"2":0,"3":0},"f":{"0":0,"1":0,"2":0},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Header.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Header.vue","statementMap":{"0":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":1},"f":{},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageSkeleton.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageSkeleton.vue","statementMap":{"0":{"start":{"line":13,"column":0},"end":{"line":13,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":1},"f":{},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageUnsplash.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageUnsplash.vue","statementMap":{"0":{"start":{"line":26,"column":0},"end":{"line":26,"column":null}},"1":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}},"2":{"start":{"line":45,"column":0},"end":{"line":45,"column":null}},"3":{"start":{"line":55,"column":0},"end":{"line":55,"column":null}},"4":{"start":{"line":56,"column":0},"end":{"line":64,"column":null}},"5":{"start":{"line":57,"column":0},"end":{"line":62,"column":null}},"6":{"start":{"line":60,"column":0},"end":{"line":60,"column":null}},"7":{"start":{"line":61,"column":0},"end":{"line":61,"column":null}},"8":{"start":{"line":62,"column":0},"end":{"line":62,"column":null}},"9":{"start":{"line":64,"column":0},"end":{"line":64,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":44,"column":0},"end":{"line":44,"column":null}},"loc":{"start":{"line":44,"column":0},"end":{"line":49,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":54,"column":0},"end":{"line":54,"column":null}},"loc":{"start":{"line":54,"column":0},"end":{"line":65,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":57,"column":0},"end":{"line":57,"column":null}},"loc":{"start":{"line":57,"column":0},"end":{"line":62,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":62,"column":0},"end":{"line":62,"column":null}},"loc":{"start":{"line":62,"column":0},"end":{"line":62,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":56,"column":0},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":0},"end":{"line":64,"column":null}},{"start":{"line":56,"column":0},"end":{"line":64,"column":null}}]}},"s":{"0":1,"1":1,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0,0]}} +,"/Users/viricel/Sites/fruit-project/src/components/Grid/DeleteItem.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Grid/DeleteItem.vue","statementMap":{"0":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}},"1":{"start":{"line":33,"column":0},"end":{"line":33,"column":null}},"2":{"start":{"line":36,"column":0},"end":{"line":36,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}},"loc":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":26,"column":0},"end":{"line":26,"column":null}},"loc":{"start":{"line":26,"column":0},"end":{"line":30,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":32,"column":0},"end":{"line":32,"column":null}},"loc":{"start":{"line":32,"column":0},"end":{"line":34,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":35,"column":0},"end":{"line":35,"column":null}},"loc":{"start":{"line":35,"column":0},"end":{"line":37,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":36,"column":0},"end":{"line":36,"column":null}},"loc":{"start":{"line":36,"column":0},"end":{"line":36,"column":null}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Grid/Grid.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Grid/Grid.vue","statementMap":{"0":{"start":{"line":16,"column":0},"end":{"line":16,"column":null}},"1":{"start":{"line":17,"column":0},"end":{"line":17,"column":null}},"2":{"start":{"line":18,"column":0},"end":{"line":18,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0,"1":0,"2":0},"f":{},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Grid/GridItem.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Grid/GridItem.vue","statementMap":{"0":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}},"1":{"start":{"line":24,"column":0},"end":{"line":24,"column":null}},"2":{"start":{"line":37,"column":0},"end":{"line":37,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":0},"end":{"line":36,"column":null}},"loc":{"start":{"line":36,"column":0},"end":{"line":38,"column":null}}}},"branchMap":{},"s":{"0":1,"1":1,"2":1},"f":{"0":1},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Grid/GridItemSkeleton.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Grid/GridItemSkeleton.vue","statementMap":{"0":{"start":{"line":16,"column":0},"end":{"line":16,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0},"f":{},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/views/Fruit.vue": {"path":"/Users/viricel/Sites/fruit-project/src/views/Fruit.vue","statementMap":{"0":{"start":{"line":28,"column":0},"end":{"line":28,"column":null}},"1":{"start":{"line":29,"column":0},"end":{"line":29,"column":null}},"2":{"start":{"line":35,"column":0},"end":{"line":35,"column":null}},"3":{"start":{"line":41,"column":0},"end":{"line":41,"column":null}},"4":{"start":{"line":47,"column":0},"end":{"line":47,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":34,"column":0},"end":{"line":34,"column":null}},"loc":{"start":{"line":34,"column":0},"end":{"line":38,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":40,"column":0},"end":{"line":40,"column":null}},"loc":{"start":{"line":40,"column":0},"end":{"line":42,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":46,"column":0},"end":{"line":46,"column":null}},"loc":{"start":{"line":46,"column":0},"end":{"line":48,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":47,"column":0},"end":{"line":47,"column":null}},"type":"cond-expr","locations":[{"start":{"line":47,"column":0},"end":{"line":47,"column":null}},{"start":{"line":47,"column":0},"end":{"line":47,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0,0]}} +,"/Users/viricel/Sites/fruit-project/src/views/Fruits.vue": {"path":"/Users/viricel/Sites/fruit-project/src/views/Fruits.vue","statementMap":{"0":{"start":{"line":13,"column":0},"end":{"line":13,"column":null}},"1":{"start":{"line":14,"column":0},"end":{"line":14,"column":null}},"2":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}},"3":{"start":{"line":28,"column":0},"end":{"line":28,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":0},"end":{"line":22,"column":null}},"loc":{"start":{"line":22,"column":0},"end":{"line":26,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}},"loc":{"start":{"line":27,"column":0},"end":{"line":29,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":0},"end":{"line":28,"column":null}},"loc":{"start":{"line":28,"column":0},"end":{"line":28,"column":null}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0},"f":{"0":0,"1":0,"2":0},"b":{}} } diff --git a/coverage/lcov-report/components/AddFruit.vue.html b/coverage/lcov-report/components/AddFruit.vue.html new file mode 100644 index 0000000..8001717 --- /dev/null +++ b/coverage/lcov-report/components/AddFruit.vue.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for components/AddFruit.vue + + + + + + + + +
+
+

All files / components AddFruit.vue

+
+ +
+ 25% + Statements + 1/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 25% + Lines + 1/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div class="modal">
+    <h2>New Fruit</h2>
+    <form id="new-fruit">
+      <!-- name -->
+      <p>
+        <input ref="autofocus" type="text" v-model="fruit.name" placeholder="Name" />
+      </p>
+ 
+      <!-- image finder (with Unsplash API) -->
+      <ImageUnsplash
+        @getValue="getImage"
+        label="Image"
+        placeholder="Search: strawberry, apple ..."
+      />
+ 
+      <div class="input-group">
+        <!-- taste -->
+        <input type="text" v-model="fruit.taste" placeholder="Taste" />
+ 
+        <!-- color -->
+        <input type="color" v-model="fruit.color" placeholder="Color" />
+      </div>
+ 
+      <!-- price -->
+      <p>
+        <input type="number" v-model="fruit.price" placeholder="Price" />
+      </p>
+ 
+      <!-- expires -->
+      <p>
+        <input type="date" v-model="fruit.expires" placeholder="Expiry date" />
+      </p>
+ 
+      <!-- description -->
+      <p>
+        <textarea v-model="fruit.description" placeholder="Message ..." />
+      </p>
+    </form>
+  </div>
+</template>
+ 
+<script>
+import ImageUnsplash from "./Form/ImageUnsplash/ImageUnsplash";
+ 
+export default {
+  name: "AddFruit",
+  components: { ImageUnsplash },
+  data() {
+    return {
+      fruit: {}
+    };
+  },
+  mounted() {
+    this.$refs["autofocus"].focus();
+  },
+  methods: {
+    getImage(url) {
+      this.fruit.image = url;
+    }
+  }
+};
+</script>
+ 
+<style lang="less">
+.modal {
+  position: absolute;
+  top: @headerHeight;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 100%;
+  background-color: @color-2;
+  padding: 1rem;
+  z-index: 14;
+ 
+  form {
+    border: 2px solid @color-1;
+    border-radius: 10px;
+    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='88' viewBox='0 0 88 88'%3E%3Cg fill='%230c9696' fill-opacity='0.35'%3E%3Cpath fill-rule='evenodd' d='M29.42 29.41c.36-.36.58-.85.58-1.4V0h-4v26H0v4h28c.55 0 1.05-.22 1.41-.58h.01zm0 29.18c.36.36.58.86.58 1.4V88h-4V62H0v-4h28c.56 0 1.05.22 1.41.58zm29.16 0c-.36.36-.58.85-.58 1.4V88h4V62h26v-4H60c-.55 0-1.05.22-1.41.58h-.01zM62 26V0h-4v28c0 .55.22 1.05.58 1.41.37.37.86.59 1.41.59H88v-4H62zM18 36c0-1.1.9-2 2-2h10a2 2 0 1 1 0 4H20a2 2 0 0 1-2-2zm0 16c0-1.1.9-2 2-2h10a2 2 0 1 1 0 4H20a2 2 0 0 1-2-2zm16-26a2 2 0 0 1 2-2 2 2 0 0 1 2 2v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-4zm16 0a2 2 0 0 1 2-2 2 2 0 0 1 2 2v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-4zM34 58a2 2 0 0 1 2-2 2 2 0 0 1 2 2v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-4zm16 0a2 2 0 0 1 2-2 2 2 0 0 1 2 2v4a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-4zM34 78a2 2 0 0 1 2-2 2 2 0 0 1 2 2v6a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-6zm16 0a2 2 0 0 1 2-2 2 2 0 0 1 2 2v6a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-6zM34 4a2 2 0 0 1 2-2 2 2 0 0 1 2 2v6a2 2 0 0 1-2 2 2 2 0 0 1-2-2V4zm16 0a2 2 0 0 1 2-2 2 2 0 0 1 2 2v6a2 2 0 0 1-2 2 2 2 0 0 1-2-2V4zm-8 82a2 2 0 1 1 4 0v2h-4v-2zm0-68a2 2 0 1 1 4 0v10a2 2 0 1 1-4 0V18zM66 4a2 2 0 1 1 4 0v8a2 2 0 1 1-4 0V4zm0 72a2 2 0 1 1 4 0v8a2 2 0 1 1-4 0v-8zm-48 0a2 2 0 1 1 4 0v8a2 2 0 1 1-4 0v-8zm0-72a2 2 0 1 1 4 0v8a2 2 0 1 1-4 0V4zm24-4h4v2a2 2 0 1 1-4 0V0zm0 60a2 2 0 1 1 4 0v10a2 2 0 1 1-4 0V60zm14-24c0-1.1.9-2 2-2h10a2 2 0 1 1 0 4H58a2 2 0 0 1-2-2zm0 16c0-1.1.9-2 2-2h10a2 2 0 1 1 0 4H58a2 2 0 0 1-2-2zm-28-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm8 26a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm16 0a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM36 20a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm16 0a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-8-8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 68a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm16-34a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm16-12a2 2 0 1 0 0 4 6 6 0 1 1 0 12 2 2 0 1 0 0 4 10 10 0 1 0 0-20zm-64 0a2 2 0 1 1 0 4 6 6 0 1 0 0 12 2 2 0 1 1 0 4 10 10 0 1 1 0-20zm56-12a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0 48a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-48 0a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-48a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm24 32a10 10 0 1 1 0-20 10 10 0 0 1 0 20zm0-4a6 6 0 1 0 0-12 6 6 0 0 0 0 12zm36-36a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-4a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM10 44c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4h-8a2 2 0 0 1-2-2zm56 0c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4h-8a2 2 0 0 1-2-2zm8 24c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4h-8a2 2 0 0 1-2-2zM3 68c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4H5a2 2 0 0 1-2-2zm0-48c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4H5a2 2 0 0 1-2-2zm71 0c0-1.1.9-2 2-2h8a2 2 0 1 1 0 4h-8a2 2 0 0 1-2-2zm6 66a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-4a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM8 86a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-4a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-68A6 6 0 1 1 8 2a6 6 0 0 1 0 12zm0-4a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm36 36a2 2 0 1 0 0-4 2 2 0 0 0 0 4z'/%3E%3C/g%3E%3C/svg%3E");
+    background-attachment: scroll;
+    background-color: rgba(0, 0, 0, 0.06);
+    box-shadow: 0 1px 4px 1px #d2d2f2;
+    padding: 1rem;
+ 
+    .input-group {
+      display: flex;
+      align-items: center;
+      margin: 1rem 0;
+ 
+      [type="color"] {
+        width: 35%;
+        height: 48px;
+      }
+ 
+      :first-child {
+        margin-right: 1rem;
+      }
+    }
+ 
+    input,
+    .image-unsplash {
+      box-sizing: border-box;
+      width: 100%;
+      border-radius: 4px;
+      border: 1px solid #cecece;
+      background-color: @color-2;
+      padding: 0.75rem 1rem;
+    }
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Form/ImageUnsplash/ImageSkeleton.vue.html b/coverage/lcov-report/components/Form/ImageUnsplash/ImageSkeleton.vue.html new file mode 100644 index 0000000..f5eee60 --- /dev/null +++ b/coverage/lcov-report/components/Form/ImageUnsplash/ImageSkeleton.vue.html @@ -0,0 +1,148 @@ + + + + + + Code coverage report for components/Form/ImageUnsplash/ImageSkeleton.vue + + + + + + + + +
+
+

All files / components/Form/ImageUnsplash ImageSkeleton.vue

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <VueContentLoading
+    :style="{ backgroundColor: '#ffffff', padding: '1rem', borderRadius: '10px' }"
+    primary="#cecece"
+    :width="300"
+    :height="180"
+  >
+    <rect x="0" y="0" rx="4" ry="4" width="300" height="180" />
+  </VueContentLoading>
+</template>
+ 
+<script>
+import VueContentLoading from "vue-content-loading";
+ 
+export default {
+  name: "ImageSkeleton",
+  components: {
+    VueContentLoading
+  }
+};
+</script>
+ 
+<style lang="less"></style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Form/ImageUnsplash/ImageUnsplash.vue.html b/coverage/lcov-report/components/Form/ImageUnsplash/ImageUnsplash.vue.html new file mode 100644 index 0000000..d7bd160 --- /dev/null +++ b/coverage/lcov-report/components/Form/ImageUnsplash/ImageUnsplash.vue.html @@ -0,0 +1,454 @@ + + + + + + Code coverage report for components/Form/ImageUnsplash/ImageUnsplash.vue + + + + + + + + +
+
+

All files / components/Form/ImageUnsplash ImageUnsplash.vue

+
+ +
+ 20% + Statements + 2/10 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 20% + Lines + 2/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div class="image-unsplash">
+    <label for="search-unsplash">{{ label }}</label>
+    <!-- Loading placeholder -->
+    <ImageSkeleton v-if="loading" />
+ 
+    <!-- Image preview -->
+    <img
+      class="preview"
+      v-if="!loading && !error && preview"
+      :src="preview.urls.regular"
+      :alt="preview.alt_description"
+    />
+ 
+    <!-- API error messages -->
+    <p class="error" v-if="error">{{ error }}</p>
+ 
+    <!-- Search input -->
+    <div class="search-box">
+      <input id="search-unsplash" type="search" :placeholder="placeholder" @change="handleSearch" />
+    </div>
+  </div>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+import ImageSkeleton from "./ImageSkeleton";
+ 
+export default {
+  name: "ImageUnsplash",
+  components: {
+    ImageSkeleton
+  },
+  props: {
+    label: {
+      type: String,
+      default: "Image (from Unsplash)"
+    },
+    placeholder: {
+      type: String,
+      default: "Type anything !"
+    }
+  },
+  data() {
+    return {
+      error: null,
+      preview: null
+    };
+  },
+  computed: {
+    ...mapState(["loading"])
+  },
+  methods: {
+    async handleSearch(e) {
+      this.error = null;
+      if (e.target.value != "") {
+        await this.$store
+          .dispatch("getImageFromUnsplash", e.target.value)
+          .then(res => {
+            this.preview = res;
+            this.$emit("getValue", res.urls.regular);
+          })
+          .catch(err => (this.error = err.message));
+      } else this.preview = null;
+    }
+  }
+};
+</script>
+ 
+<style scoped lang="less">
+.image-unsplash {
+  label {
+    display: block;
+    font-weight: bold;
+    margin-bottom: 0.5rem;
+  }
+ 
+  .preview,
+  .skeleton {
+    margin-bottom: 1rem;
+  }
+ 
+  .preview {
+    width: 100%;
+    object-fit: scale-down;
+    height: 180px;
+  }
+ 
+  .error {
+    color: @text-error;
+    text-align: center;
+  }
+ 
+  .search-box {
+    position: relative;
+    z-index: 0;
+ 
+    &:focus-within::after {
+      opacity: 1;
+    }
+ 
+    &::after {
+      content: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 350.439 350.439' style='enable-background:new 0 0 350.439 350.439;' xml:space='preserve'%3E%3Cg%3E%3Cpath d='M312.856,36.464H202.507c-4.87,0-8.83,3.961-8.83,8.832v138.422H52.371c-4.87,0-8.832,3.973-8.832,8.843v108.023 c0,4.87,3.961,8.831,8.832,8.831l260.474-0.071c4.873,0,8.838-3.962,8.838-8.843l0.011-255.211 C321.701,40.425,317.737,36.464,312.856,36.464z M175.216,253.617c0,5.724-4.635,10.353-10.356,10.353h-57.814 c-0.392,0-0.775-0.022-1.155-0.065v0.887l8.294,21.002c0.281,0.7,0.057,1.51-0.551,1.965c-0.301,0.229-0.658,0.344-1.013,0.344 c-0.364,0-0.722-0.12-1.025-0.355l-41.251-31.715c-0.416-0.318-0.657-0.816-0.657-1.33c0-0.531,0.241-1.023,0.657-1.345 l41.251-31.712c0.6-0.463,1.433-0.463,2.038-0.011c0.603,0.459,0.827,1.258,0.551,1.958l-7.776,19.694 c0.21-0.011,0.418-0.033,0.637-0.033h47.462v-34.715c0-5.724,4.637-10.353,10.352-10.353c5.721,0,10.356,4.629,10.356,10.353 V253.617z M332.215,7.41H174.623c-10.062,0-18.221,8.159-18.221,18.225v126.679H18.223C8.159,152.314,0,160.479,0,170.541v154.267 c0,10.063,8.159,18.222,18.223,18.222h157.588c0.346,0,0.667-0.087,1.008-0.099h155.375c10.065,0,18.228-8.164,18.228-18.232 V180.074c0-0.066,0.018-0.121,0.018-0.176V25.635C350.439,15.569,342.273,7.41,332.215,7.41z M329.535,300.512 c0,9.205-7.483,16.69-16.69,16.69H204.052c-0.078,0.043-0.383,0.076-0.705,0.076H52.371c-9.202,0-16.688-7.485-16.688-16.689 V192.571c0-9.209,7.485-16.689,16.688-16.689h133.453V45.295c0-9.201,7.485-16.687,16.684-16.687h110.349 c9.204,0,16.689,7.486,16.689,16.687L329.535,300.512z'/%3E%3C/g%3E%3C/svg%3E");
+      position: absolute;
+      z-index: 1;
+      top: 50%;
+      right: 0.3rem;
+      width: 24px;
+      height: 24px;
+      transform: translateY(-50%);
+      opacity: 0.4;
+    }
+ 
+    [type="search"] {
+      padding-right: 2.35rem;
+      border: none;
+      background-color: lighten(#cecece, 15%);
+    }
+  }
+ 
+  [type="file"] {
+    border: none;
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Form/ImageUnsplash/index.html b/coverage/lcov-report/components/Form/ImageUnsplash/index.html new file mode 100644 index 0000000..da39098 --- /dev/null +++ b/coverage/lcov-report/components/Form/ImageUnsplash/index.html @@ -0,0 +1,125 @@ + + + + + + Code coverage report for components/Form/ImageUnsplash + + + + + + + + +
+
+

All files components/Form/ImageUnsplash

+
+ +
+ 27.27% + Statements + 3/11 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 27.27% + Lines + 3/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
ImageSkeleton.vue +
+
100%1/1100%0/0100%0/0100%1/1
ImageUnsplash.vue +
+
20%2/100%0/20%0/420%2/10
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Grid/DeleteItem.vue.html b/coverage/lcov-report/components/Grid/DeleteItem.vue.html new file mode 100644 index 0000000..e66dfce --- /dev/null +++ b/coverage/lcov-report/components/Grid/DeleteItem.vue.html @@ -0,0 +1,358 @@ + + + + + + Code coverage report for components/Grid/DeleteItem.vue + + + + + + + + +
+
+

All files / components/Grid DeleteItem.vue

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div>
+    <button class="delete-btn" @click="showPrompt">
+      🚮
+    </button>
+    <div v-if="openPrompt" :class="{ open: openPrompt }" class="prompt">
+      <h3>You will delete '{{ item.name }}'?</h3>
+      <div class="actions">
+        <button class="btn btn-cancel" @click="openPrompt = false">No</button>
+        <button class="btn btn-success" @click="removeFruit(item.id)">Yes</button>
+      </div>
+    </div>
+  </div>
+</template>
+ 
+<script>
+export default {
+  name: "DeleteItem",
+  props: {
+    item: Object,
+    redirect: {
+      type: Function,
+      default: () => {}
+    }
+  },
+  data() {
+    return {
+      openPrompt: false
+    };
+  },
+  methods: {
+    showPrompt() {
+      this.openPrompt = true;
+    },
+    removeFruit(id) {
+      this.$store.dispatch("removeFruit", id).then(() => this.redirect());
+    }
+  }
+};
+</script>
+ 
+<style scoped lang="less">
+.prompt {
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: 2;
+  background: rgb(230, 107, 107);
+  background: linear-gradient(90deg, rgba(230, 107, 107, 1) 0%, rgba(214, 48, 49, 1) 100%);
+  width: 0;
+  height: 0;
+  transition: all 0.4s ease-in-out;
+  color: @color-2;
+  display: flex;
+  flex-flow: column;
+  align-items: center;
+  justify-content: center;
+ 
+  &.open {
+    width: 100%;
+    height: 100%;
+  }
+ 
+  .btn {
+    border: none;
+    border-radius: 4px;
+    color: @color-2;
+    padding: 0.5rem 1.35rem;
+    margin: 0 0.5rem;
+  }
+ 
+  .btn-success {
+    background-color: #2ecc71;
+  }
+ 
+  .btn-cancel {
+    background-color: darken(#cecece, 15%);
+  }
+}
+ 
+.delete-btn {
+  position: absolute;
+  z-index: 1;
+  top: 0;
+  right: 0;
+  width: 55px;
+  padding: 0.75rem 0.75rem 1.35rem 1.35rem;
+  background: rgb(230, 107, 107);
+  background: linear-gradient(180deg, rgba(230, 107, 107, 0.6) 0%, rgba(214, 48, 49, 1) 100%);
+  border: none;
+  border-bottom-left-radius: 100%;
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Grid/Grid.vue.html b/coverage/lcov-report/components/Grid/Grid.vue.html new file mode 100644 index 0000000..f50ed69 --- /dev/null +++ b/coverage/lcov-report/components/Grid/Grid.vue.html @@ -0,0 +1,328 @@ + + + + + + Code coverage report for components/Grid/Grid.vue + + + + + + + + +
+
+

All files / components/Grid Grid.vue

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div :class="{ error: !loading && !data.length }" class="grid">
+    <!-- Loading placeholder -->
+    <GridItemSkeleton v-if="loading" />
+    <GridItemSkeleton v-if="loading" />
+ 
+    <!-- Items -->
+    <GridItem v-else :key="item.id" v-for="item in data" :item="item" />
+ 
+    <!-- Error messages -->
+    <p v-if="!loading && !data.length" class="alert"><b>💡 Restart API</b>: 0 fruits !</p>
+  </div>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+import GridItemSkeleton from "./GridItemSkeleton";
+import GridItem from "./GridItem";
+ 
+export default {
+  name: "Grid",
+  components: {
+    GridItemSkeleton,
+    GridItem
+  },
+  props: {
+    data: Array
+  },
+  computed: {
+    ...mapState(["loading"])
+  }
+};
+</script>
+ 
+<style scoped lang="less">
+.grid {
+  display: grid;
+  grid-template-columns: 1fr;
+  column-gap: 1rem;
+  row-gap: 1.5rem;
+ 
+  &.error {
+    display: block;
+  }
+ 
+  @media screen and (min-width: @md) {
+    grid-template-columns: repeat(2, 1fr);
+  }
+ 
+  @media screen and (min-width: @lg) {
+    grid-template-columns: repeat(3, 1fr);
+  }
+ 
+  @media screen and (min-width: @xl) {
+    grid-template-columns: repeat(4, 1fr);
+  }
+ 
+  .alert {
+    box-sizing: border-box;
+    margin: 0 auto;
+    width: 80%;
+    background-color: @color-3;
+    color: @color-2;
+    padding: 1rem 1.5rem;
+    border-radius: 4px;
+ 
+    @media screen and (min-width: @sm) {
+      width: 50%;
+      max-width: 535px;
+    }
+ 
+    pre {
+      padding: 1rem;
+      border-radius: 4px;
+      background-color: rgb(45, 48, 55);
+ 
+      span {
+        color: @color-3;
+      }
+    }
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Grid/GridItem.vue.html b/coverage/lcov-report/components/Grid/GridItem.vue.html new file mode 100644 index 0000000..d56ed99 --- /dev/null +++ b/coverage/lcov-report/components/Grid/GridItem.vue.html @@ -0,0 +1,412 @@ + + + + + + Code coverage report for components/Grid/GridItem.vue + + + + + + + + +
+
+

All files / components/Grid GridItem.vue

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <article class="grid-item">
+    <DeleteItem v-if="deleteMode" :item="item" />
+    <router-link :to="`/fruit/${item.id}`">
+      <div class="thumbnail">
+        <img :src="item.image" :alt="item.name" />
+      </div>
+      <section>
+        <h3>
+          {{ item.name }}
+          <span class="tag" :style="{ backgroundColor: item.color }">{{ item.taste }}</span>
+        </h3>
+ 
+        <hr />
+ 
+        <p class="price">${{ item.price | noDecimal }}</p>
+      </section>
+    </router-link>
+  </article>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+import DeleteItem from "./DeleteItem";
+ 
+export default {
+  name: "GridItem",
+  components: { DeleteItem },
+  props: {
+    item: Object
+  },
+  computed: {
+    ...mapState(["deleteMode"])
+  },
+  filters: {
+    noDecimal(value) {
+      return parseInt(value).toFixed();
+    }
+  }
+};
+</script>
+ 
+<style scoped lang="less">
+.grid-item {
+  position: relative;
+  z-index: 0;
+  background-color: @color-2;
+  border-radius: 10px;
+  overflow: hidden;
+ 
+  &:hover .thumbnail img {
+    transform: scale(1.1);
+  }
+ 
+  a {
+    display: block;
+    color: inherit;
+ 
+    .thumbnail {
+      height: 285px;
+      overflow: hidden;
+      box-shadow: 0 1px 4px 1px #d2d2f2;
+ 
+      img {
+        border-radius: 10px 10px 0 0;
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+        max-width: 100%;
+        transition: transform 0.4s ease-in-out;
+      }
+    }
+ 
+    section {
+      padding: 1.5rem 1rem;
+ 
+      h3 {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-bottom: 0.55rem;
+      }
+ 
+      hr {
+        width: 100px;
+        color: #cece;
+        margin: 1.35rem auto;
+      }
+ 
+      .tag {
+        border-radius: 25px;
+        padding: 0.35rem 0.75rem;
+        margin-left: 0.75rem;
+        color: #ffffff;
+        font-size: 14px;
+        font-weight: bold;
+        text-align: center;
+        text-transform: lowercase;
+      }
+ 
+      .price {
+        text-align: center;
+        margin: 0;
+        font-size: 28px;
+        font-weight: bold;
+        color: #ff9700;
+      }
+    }
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Grid/GridItemSkeleton.vue.html b/coverage/lcov-report/components/Grid/GridItemSkeleton.vue.html new file mode 100644 index 0000000..707288f --- /dev/null +++ b/coverage/lcov-report/components/Grid/GridItemSkeleton.vue.html @@ -0,0 +1,157 @@ + + + + + + Code coverage report for components/Grid/GridItemSkeleton.vue + + + + + + + + +
+
+

All files / components/Grid GridItemSkeleton.vue

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <VueContentLoading
+    :style="{ backgroundColor: '#ffffff', padding: '1rem', borderRadius: '10px' }"
+    primary="#cecece"
+    :width="300"
+    :height="220"
+  >
+    <rect x="0" y="0" rx="4" ry="4" width="100%" height="100" />
+    <rect x="30" y="110" rx="4" ry="4" width="80%" height="15" />
+    <rect x="100px" y="150" width="100" height="2" />
+    <rect x="100px" y="175" rx="4" ry="4" width="100" height="35" />
+  </VueContentLoading>
+</template>
+ 
+<script>
+import VueContentLoading from "vue-content-loading";
+ 
+export default {
+  name: "GridItemSkeleton",
+  components: {
+    VueContentLoading
+  }
+};
+</script>
+ 
+<style lang="less"></style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Grid/index.html b/coverage/lcov-report/components/Grid/index.html new file mode 100644 index 0000000..4469d56 --- /dev/null +++ b/coverage/lcov-report/components/Grid/index.html @@ -0,0 +1,155 @@ + + + + + + Code coverage report for components/Grid + + + + + + + + +
+
+

All files components/Grid

+
+ +
+ 30% + Statements + 3/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 16.67% + Functions + 1/6 +
+ + +
+ 30% + Lines + 3/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
DeleteItem.vue +
+
0%0/3100%0/00%0/50%0/3
Grid.vue +
+
0%0/3100%0/0100%0/00%0/3
GridItem.vue +
+
100%3/3100%0/0100%1/1100%3/3
GridItemSkeleton.vue +
+
0%0/1100%0/0100%0/00%0/1
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/Header.vue.html b/coverage/lcov-report/components/Header.vue.html new file mode 100644 index 0000000..b156279 --- /dev/null +++ b/coverage/lcov-report/components/Header.vue.html @@ -0,0 +1,382 @@ + + + + + + Code coverage report for components/Header.vue + + + + + + + + +
+
+

All files / components Header.vue

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <header id="header" class="main-nav">
+    <router-link to="/">
+      <img src="https://www.cycloid.io/themes/cycloid/images/owl_logo.png" alt="Cycloid.io" />
+      <h1>Fruits</h1>
+    </router-link>
+ 
+    <div class="actions">
+      <button
+        class="action-btn action-btn--delete"
+        @click="() => $store.commit('toggleDeleteMode')"
+      >
+        {{ deleteMode ? "&#x1F6AB;" : "&#x1f5d1;" }}
+      </button>
+      <button class="action-btn action-btn--add" @click="() => $store.commit('toggleModal')">
+        +
+      </button>
+    </div>
+  </header>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+ 
+export default {
+  name: "Header",
+  computed: {
+    ...mapState(["deleteMode"])
+  }
+};
+</script>
+ 
+<style lang="less">
+header {
+  background-color: @color-2;
+  box-shadow: 0 0px 14px 0px #cecece;
+ 
+  h1 {
+    margin: 0;
+    font-size: 28px;
+    font-weight: lighter;
+  }
+ 
+  &.main-nav {
+    position: sticky;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 15;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 1rem;
+    height: @headerHeight;
+    transition: all 0.3s ease-in-out;
+ 
+    a {
+      display: flex;
+      align-items: center;
+ 
+      img {
+        width: 35px;
+        height: 35px;
+        margin-right: 1rem;
+      }
+    }
+ 
+    .actions {
+      display: flex;
+      align-items: center;
+ 
+      .action-btn {
+        width: 42px;
+        height: 42px;
+        border: none;
+        border-radius: 50%;
+        color: @color-2;
+        font-size: 28px;
+        font-weight: lighter;
+        text-align: center;
+        margin-left: 1rem;
+ 
+        &--delete {
+          border: 1px solid @text-error;
+          background: lighten(#cecece, 10%);
+          font-size: 24px;
+          padding-top: 2px;
+        }
+ 
+        &--add {
+          background: linear-gradient(112.4deg, #1c9797 11.05%, #147171 89.93%);
+ 
+          &:hover {
+            background: linear-gradient(0deg, #1c9797 11.05%, #147171 89.93%);
+          }
+        }
+      }
+    }
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/index.html b/coverage/lcov-report/components/index.html index 123519f..583a74b 100644 --- a/coverage/lcov-report/components/index.html +++ b/coverage/lcov-report/components/index.html @@ -22,9 +22,9 @@
- 100% + 40% Statements - 1/1 + 2/5
@@ -36,16 +36,16 @@
- 100% + 0% Functions - 0/0 + 0/3
- 100% + 40% Lines - 1/1 + 2/5
@@ -54,7 +54,7 @@ Press n or j to go to the next uncovered block, b, p or k for the previous block.

-
+
@@ -72,7 +72,22 @@ - + + + + + + + + + + + + + + @@ -94,7 +109,7 @@ diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html index a30a5ce..cd67b66 100644 --- a/coverage/lcov-report/index.html +++ b/coverage/lcov-report/index.html @@ -22,30 +22,30 @@
- 60% + 22.86% Statements - 3/5 -
- - -
- 100% - Branches - 0/0 + 8/35
0% - Functions - 0/1 + Branches + 0/4
- 60% + 5.26% + Functions + 1/19 +
+ + +
+ 22.86% Lines - 3/5 + 8/35
@@ -54,7 +54,7 @@ Press n or j to go to the next uncovered block, b, p or k for the previous block.

-
+
Grid.vueAddFruit.vue +
+
25%1/4100%0/00%0/325%1/4
Header.vue
@@ -72,33 +72,63 @@ - - + - - - - - - - - - - - - - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -109,7 +139,7 @@ diff --git a/coverage/lcov-report/views/Fruit.vue.html b/coverage/lcov-report/views/Fruit.vue.html index 02c4aad..5452ce7 100644 --- a/coverage/lcov-report/views/Fruit.vue.html +++ b/coverage/lcov-report/views/Fruit.vue.html @@ -24,28 +24,28 @@
0% Statements - 0/1 + 0/5
- 100% + 0% Branches - 0/0 + 0/2
- 100% + 0% Functions - 0/0 + 0/3
0% Lines - 0/1 + 0/5
@@ -74,7 +74,130 @@ 161718 -19
components -
+
components +
100%1/1100%0/0100%0/0100%1/1
views -
-
50%2/440%2/5 100% 0/0 0%0/150%2/40/340%2/5
components/Form/ImageUnsplash +
+
27.27%3/110%0/20%0/427.27%3/11
components/Grid +
+
30%3/10100%0/016.67%1/630%3/10
views +
+
0%0/90%0/20%0/60%0/9
  +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142        @@ -82,6 +205,44 @@       +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +        @@ -92,24 +253,232 @@       +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +   
<template>
   <div>
-    <h2><span @click="() => this.$router.back()">◀</span> Details</h2>
-    {{ this.fruit }}
+    <h2><span @click="() => this.$router.push('/')">◀</span> Details</h2>
+ 
+    <article>
+      <img :src="fruit.image" :alt="fruit.name" />
+      <section>
+        <DeleteItem v-if="deleteMode" :item="fruit" :redirect="() => $router.push('/')" />
+        <h3>
+          {{ fruit.name }}
+          <span class="tag" :style="{ backgroundColor: fruit.color }">{{ fruit.taste }}</span>
+        </h3>
+ 
+        <p>{{ fruit.description }}</p>
+ 
+        <hr />
+ 
+        <p class="price">${{ fruit.price | noDecimal }}</p>
+        <div class="alert">
+          {{ "This offer " + expirationState }} {{ fruit.expires | moment("from", "now") }}
+        </div>
+      </section>
+    </article>
   </div>
 </template>
  
 <script>
 import { mapState } from "vuex";
+import DeleteItem from "@/components/Grid/DeleteItem";
+ 
 export default {
   name: "FruitDetails",
+  components: { DeleteItem },
+  data() {
+    return {
+      modalOpen: true
+    };
+  },
+  filters: {
+    noDecimal(value) {
+      return parseInt(value).toFixed();
+    }
+  },
   computed: {
-    ...mapState(["fruit"])
+    ...mapState(["fruit", "deleteMode"]),
+    expirationState() {
+      return new Date(this.fruit.expires) < new Date() ? "expired" : "expires";
+    }
   }
 };
 </script>
  
-<style></style>
+<style lang="less" scoped>
+h2 span {
+  cursor: pointer;
+}
+article {
+  display: flex;
+  align-items: center;
+  flex-flow: column;
+ 
+  img,
+  section {
+    border-radius: 10px;
+  }
+ 
+  img {
+    width: 100%;
+    object-fit: scale-down;
+    margin-bottom: 1.5rem;
+    box-shadow: 0 1px 4px 1px #d2d2f2;
+  }
+ 
+  section {
+    position: relative;
+    z-index: 0;
+    padding: 1.5rem 2rem;
+    background-color: @color-2;
+ 
+    h3 {
+      display: flex;
+      align-items: center;
+      justify-content: flex-start;
+      margin-bottom: 0.55rem;
+      font-size: 34px;
+    }
+ 
+    hr {
+      width: 100px;
+      color: #cece;
+      margin: 1.35rem auto;
+    }
+ 
+    .tag {
+      border-radius: 25px;
+      padding: 0.35rem 0.75rem;
+      margin-left: 0.75rem;
+      color: #ffffff;
+      font-size: 14px;
+      font-weight: bold;
+      text-align: center;
+      text-transform: lowercase;
+    }
+ 
+    .price {
+      text-align: center;
+      margin: 0;
+      font-size: 28px;
+      font-weight: bold;
+      color: @color-3;
+    }
+  }
+ 
+  @media screen and (min-width: @sm) {
+    flex-flow: row;
+    align-items: flex-start;
+    justify-content: center;
+ 
+    img,
+    section {
+      width: 50%;
+      max-width: 485px;
+    }
+ 
+    img {
+      max-height: 435px;
+      margin-bottom: 0;
+      margin-right: 1.5rem;
+      object-fit: cover;
+    }
+  }
+}
+ 
+.alert {
+  margin-top: 1.75rem;
+  background: linear-gradient(112.4deg, #1c9797 11.05%, #147171 89.93%);
+  color: @color-2;
+  padding: 1rem 1.5rem;
+  border-radius: 4px;
+}
+</style>
  
@@ -117,7 +486,7 @@ export default {
diff --git a/coverage/lcov-report/views/Fruits.vue.html b/coverage/lcov-report/views/Fruits.vue.html index 8ff06f4..8c8fb8f 100644 --- a/coverage/lcov-report/views/Fruits.vue.html +++ b/coverage/lcov-report/views/Fruits.vue.html @@ -22,9 +22,9 @@
- 66.67% + 0% Statements - 2/3 + 0/4
@@ -38,14 +38,14 @@
0% Functions - 0/1 + 0/3
- 66.67% + 0% Lines - 2/3 + 0/4
@@ -54,7 +54,7 @@ Press n or j to go to the next uncovered block, b, p or k for the previous block.

-
+
1 2 @@ -85,7 +85,41 @@ 27 28 29 -30  +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64        @@ -93,12 +127,21 @@       -1x -1x         +  +  +  +  +  +  +  +  +  +  +        @@ -114,16 +157,45 @@       +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +   
<template>
   <div class="fruits">
     <h2>Directory</h2>
-    <Grid :data="this.fruits" />
+    <Grid v-if="!error" :data="this.fruits" />
+    <div class="alert" v-else>
+      {{ error }}
+      <pre><span>$</span> yarn run api</pre>
+    </div>
   </div>
 </template>
  
 <script>
-import { mapState } from "vuex";
-import Grid from "@/components/Grid";
+import { mapState } from "vuex";
+import Grid from "@/components/Grid/Grid";
  
 export default {
   name: "Fruits",
@@ -131,17 +203,47 @@ export default {
   computed: {
     ...mapState(["fruits"])
   },
+  data() {
+    return {
+      error: null
+    };
+  },
   async created() {
-    await this.$store.dispatch("getFruits");
+    await this.$store.dispatch("getFruits").catch(err => (this.error = err));
   }
 };
 </script>
  
-<style lang="less">
+<style scoped lang="less">
 .fruits {
   margin: 0 auto;
   max-width: 1200px;
 }
+ 
+.alert {
+  box-sizing: border-box;
+  margin: 0 auto;
+  width: 80%;
+  background-color: @text-error;
+  color: @color-2;
+  padding: 1rem 1.5rem;
+  border-radius: 4px;
+ 
+  @media screen and (min-width: @sm) {
+    width: 50%;
+    max-width: 535px;
+  }
+ 
+  pre {
+    padding: 1rem;
+    border-radius: 4px;
+    background-color: rgb(45, 48, 55);
+ 
+    span {
+      color: @color-3;
+    }
+  }
+}
 </style>
  
@@ -150,7 +252,7 @@ export default { diff --git a/coverage/lcov-report/views/index.html b/coverage/lcov-report/views/index.html index c9915e9..904e437 100644 --- a/coverage/lcov-report/views/index.html +++ b/coverage/lcov-report/views/index.html @@ -22,30 +22,30 @@
- 50% + 0% Statements - 2/4 + 0/9
- 100% + 0% Branches - 0/0 + 0/2
0% Functions - 0/1 + 0/6
- 50% + 0% Lines - 2/4 + 0/9
@@ -54,7 +54,7 @@ Press n or j to go to the next uncovered block, b, p or k for the previous block.

-
+
@@ -77,28 +77,28 @@
- - - - - + - + + + + + - - + - - + + - - - + + + @@ -109,7 +109,7 @@ diff --git a/coverage/lcov.info b/coverage/lcov.info index 620e193..4d61ef2 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -1,34 +1,167 @@ TN: -SF:/Users/viricel/Sites/fruit-project/src/components/Grid.vue +SF:/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue +FN:49,(anonymous_1) +FN:54,(anonymous_2) +FN:58,(anonymous_3) +FNF:3 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:44,1 +DA:50,0 +DA:55,0 +DA:59,0 +LF:4 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Header.vue FNF:0 FNH:0 -DA:8,1 +DA:23,1 LF:1 LH:1 BRF:0 BRH:0 end_of_record TN: -SF:/Users/viricel/Sites/fruit-project/src/views/Fruit.vue +SF:/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageSkeleton.vue FNF:0 FNH:0 -DA:9,0 +DA:13,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageUnsplash.vue +FN:44,(anonymous_1) +FN:54,(anonymous_2) +FN:57,(anonymous_3) +FN:62,(anonymous_4) +FNF:4 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +DA:26,1 +DA:27,1 +DA:45,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:64,0 +LF:10 +LH:2 +BRDA:56,0,0,0 +BRDA:56,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Grid/DeleteItem.vue +FN:23,(anonymous_1) +FN:26,(anonymous_2) +FN:32,(anonymous_3) +FN:35,(anonymous_4) +FN:36,(anonymous_5) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:27,0 +DA:33,0 +DA:36,0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Grid/Grid.vue +FNF:0 +FNH:0 +DA:16,0 +DA:17,0 +DA:18,0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Grid/GridItem.vue +FN:36,(anonymous_1) +FNF:1 +FNH:1 +FNDA:1,(anonymous_1) +DA:23,1 +DA:24,1 +DA:37,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Grid/GridItemSkeleton.vue +FNF:0 +FNH:0 +DA:16,0 LF:1 LH:0 BRF:0 BRH:0 end_of_record TN: -SF:/Users/viricel/Sites/fruit-project/src/views/Fruits.vue -FN:18,(anonymous_1) -FNF:1 +SF:/Users/viricel/Sites/fruit-project/src/views/Fruit.vue +FN:34,(anonymous_1) +FN:40,(anonymous_2) +FN:46,(anonymous_3) +FNF:3 FNH:0 FNDA:0,(anonymous_1) -DA:9,1 -DA:10,1 -DA:19,0 -LF:3 -LH:2 +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:28,0 +DA:29,0 +DA:35,0 +DA:41,0 +DA:47,0 +LF:5 +LH:0 +BRDA:47,0,0,0 +BRDA:47,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/views/Fruits.vue +FN:22,(anonymous_1) +FN:27,(anonymous_2) +FN:28,(anonymous_3) +FNF:3 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:13,0 +DA:14,0 +DA:23,0 +DA:28,0 +LF:4 +LH:0 BRF:0 BRH:0 end_of_record diff --git a/tests/unit/GridItem.spec.js b/tests/unit/GridItem.spec.js index b2bc52d..e4b83a5 100644 --- a/tests/unit/GridItem.spec.js +++ b/tests/unit/GridItem.spec.js @@ -1,9 +1,21 @@ -import { mount, RouterLinkStub } from "@vue/test-utils"; -import GridItem from "@/components/GridItem.vue"; +import { mount, RouterLinkStub, createLocalVue } from "@vue/test-utils"; +import Vuex from "vuex"; +import GridItem from "@/components/Grid/GridItem.vue"; + +const localVue = createLocalVue(); +localVue.use(Vuex); describe("Test GridItem.", () => { + let store; + + beforeEach(() => { + store = new Vuex.Store(); + }); + it("checks link.", async () => { const wrapper = mount(GridItem, { + store, + localVue, propsData: { item: { id: 3, diff --git a/tests/unit/global.spec.js b/tests/unit/global.spec.js index 6a49960..b70ab6f 100644 --- a/tests/unit/global.spec.js +++ b/tests/unit/global.spec.js @@ -1,14 +1,24 @@ -import { mount } from "@vue/test-utils"; +import { mount, createLocalVue } from "@vue/test-utils"; +import Vuex from "vuex"; import App from "@/App.vue"; +const localVue = createLocalVue(); +localVue.use(Vuex); + describe("App", () => { - const wrapper = mount(App, { stubs: ["router-view", "router-link"] }); + let store; + + beforeEach(() => { + store = new Vuex.Store(); + }); it("should be a Vue instance", () => { + const wrapper = mount(App, { store, localVue, stubs: ["router-link", "router-view"] }); expect(wrapper.vm).toBeTruthy(); }); it("renders correctly", () => { + const wrapper = mount(App, { store, localVue, stubs: ["router-link", "router-view"] }); expect(wrapper.find("#app")).toBeTruthy(); }); });
0%0/1100%0/0100%0/00/5 0%0/10/20%0/30%0/5
Fruits.vue -
+
Fruits.vue +
66.67%2/30%0/4 100% 0/0 0%0/166.67%2/30/30%0/4