diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..214388f --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not dead diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c24743d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 100 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..d2f00e3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,22 @@ +module.exports = { + root: true, + env: { + node: true + }, + extends: ["plugin:vue/essential", "plugin:prettier/recommended", "eslint:recommended"], + parserOptions: { + parser: "babel-eslint" + }, + rules: { + "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", + "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" + }, + overrides: [ + { + files: ["**/__tests__/*.{j,t}s?(x)", "**/tests/unit/**/*.spec.{j,t}s?(x)"], + env: { + jest: true + } + } + ] +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ec8281 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +.DS_Store +node_modules +/dist + +/tests/e2e/videos/ +/tests/e2e/screenshots/ + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..6665a53 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +13.12.0 diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..3c9ecc6 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,39 @@ +# fruit-project + +## Project setup +``` +yarn install +``` + +### Compiles and hot-reloads for development +``` +yarn serve +``` + +### Compiles and minifies for production +``` +yarn build +``` + +### Run your unit tests +``` +yarn test:unit +``` + +### Run your end-to-end tests +``` +yarn test:e2e +``` + +### Lints and fixes files +``` +yarn lint +``` + +### Run fruit-api +``` +yarn run api +``` + +### Customize configuration +See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/README.md b/README.md index 8fd8899..0232699 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Netlify Status](https://api.netlify.com/api/v1/badges/59d8863c-1e26-4e92-8066-5ab271ae6a35/deploy-status)](https://app.netlify.com/sites/elated-raman-ffa420/deploys) # fruit-project A test project for Cycloid.io @@ -10,26 +11,57 @@ You've been given the task of creating a simple application with create/read/del ## Task - [x] Create a private repository on Github. -- [ ] Create a new Vue project using Vue-CLI within the new repository: you may use any preprocessors, testing frameworks, linting etc that you like. -- [ ] Create a branch off of master, commit all your work to this new branch. -- [ ] When you are finished, open a PR to master (but do not merge it). In the PR description, copy, paste and answer the following: +- [x] Create a new Vue project using Vue-CLI within the new repository: you may use any preprocessors, testing frameworks, linting etc that you like. +- [x] Create a branch off of master, commit all your work to this new branch. +- [x] When you are finished, open a PR to master (but do not merge it). In the PR description, copy, paste and answer the following: -``` - ### Your name +--- +## Feedbacks - ### What was challenging? +### Your name +NoƩ Viricel - ### What did you enjoy doing? +### What was challenging? +- Cypress.io, as I never used it before, I started to learn the basis from their documentation. It looks very interesting in a product quality point of view, I never had the occasion to go that far in a product development process. +- A bit tricky at first to choose which API data to keep. + +### What did you enjoy doing? +I appreciated the opportunity to imagine an app from a raw array of data. With no graphical support of any kind. It gave me the opportunity to truly showcase my creativity and skills on different subject. +I have taken the time to confirm knowledge and go further into testing data store (Vuex). + +*_**Spoiler:** I admit that I tried to stick to your graphic environement_* + +### If you had more time, what would you improve/do differently? + - Improve "Component's dynamic imports" browser support by using Async components, it would offer more control over Component's loading / error states. + - Use CSS Framework (I'm fond of AntDesign and Tailwind CSS) + - CSS Module as the app will grow, offering styles more modularity. + - Vue.js Composition API on a larger app. + - Form and Props validation. + - Page Transitions + - Better loading state management + - Setup .env file for environnement isolation (dev / test / prod). + - Work on CSS Accessibility + - Caching & Lazy Loading + - Inject axios globally (as $http) + - Notification System (Errors, Infos, Warning, Success) + - More unit test + - Definitely more End-to-End test :) + - and probably more ... - ### If you had more time, what would you improve/do differently? ### How much time (more or less) it took you to complete the task? + I've made this app in 5 days of code, more or less 25 hours ... (I did count commits timestamps :weary:) + - ### What do you think about the task itself? (Was it a good experience? If not why?) + ### What do you think about the task itself? (Was it a good experience? If not why? + I believe it's a good exercise with enough constraints to let you express yourself (in a coder's mind I mean). + I think that this task allows to approach each stage of a Frontent project conception. + + *I rather be tested like that than with a bulk of logic tests (that I find arbitrary) as I am more in a situation to think and develop ideas.* ### Summary in a gif -``` -- [ ] Invite us to your repository: @chayaline, @emilyrosina, @adamwardecki, @dangzo, @thomas-lhuillier, @SavanovicN & @Sergeon + +- [x] Invite us to your repository: @chayaline, @emilyrosina, @adamwardecki, @dangzo, @thomas-lhuillier, @SavanovicN & @Sergeon ## The specification @@ -57,10 +89,10 @@ The API is using the ESM module loader so please make sure that you have at leas ``` npm i fruit-api ``` -- [ ] Add `"api": "fruit-api"` to the scripts section of your package.json file. -- [ ] Run `npm run api` to serve the fruit-api you can view the API documentation at https://localhost:3000 (or another port number, if 3000 is already in use). +- [x] Add `"api": "fruit-api"` to the scripts section of your package.json file. +- [x] Run `npm run api` to serve the fruit-api you can view the API documentation at https://localhost:3000 (or another port number, if 3000 is already in use). **Recommended documentation** | Scaffolding | State Management | Routing | | --------------------------------- | ------------------------------ | -------------------------------------- | -| [Vue-CLI](https://cli.vuejs.org/) | [Vuex](https://vuex.vuejs.org) | [Vue-router](https://router.vuejs.org) | \ No newline at end of file +| [Vue-CLI](https://cli.vuejs.org/) | [Vuex](https://vuex.vuejs.org) | [Vue-router](https://router.vuejs.org) | diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..397abca --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ["@vue/cli-plugin-babel/preset"] +}; diff --git a/coverage/clover.xml b/coverage/clover.xml new file mode 100644 index 0000000..d8bd1b2 --- /dev/null +++ b/coverage/clover.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coverage/coverage-final.json b/coverage/coverage-final.json new file mode 100644 index 0000000..6623a49 --- /dev/null +++ b/coverage/coverage-final.json @@ -0,0 +1,11 @@ +{"/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue","statementMap":{"0":{"start":{"line":90,"column":0},"end":{"line":90,"column":null}},"1":{"start":{"line":96,"column":0},"end":{"line":96,"column":null}},"2":{"start":{"line":104,"column":0},"end":{"line":104,"column":null}},"3":{"start":{"line":105,"column":0},"end":{"line":105,"column":null}},"4":{"start":{"line":108,"column":0},"end":{"line":108,"column":null}},"5":{"start":{"line":112,"column":0},"end":{"line":112,"column":null}},"6":{"start":{"line":113,"column":0},"end":{"line":113,"column":null}},"7":{"start":{"line":116,"column":0},"end":{"line":116,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":95,"column":0},"end":{"line":95,"column":null}},"loc":{"start":{"line":95,"column":0},"end":{"line":102,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":103,"column":0},"end":{"line":103,"column":null}},"loc":{"start":{"line":103,"column":0},"end":{"line":106,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":107,"column":0},"end":{"line":107,"column":null}},"loc":{"start":{"line":107,"column":0},"end":{"line":109,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":111,"column":0},"end":{"line":111,"column":null}},"loc":{"start":{"line":111,"column":0},"end":{"line":117,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":113,"column":0},"end":{"line":113,"column":null}},"loc":{"start":{"line":113,"column":0},"end":{"line":113,"column":null}}}},"branchMap":{},"s":{"0":1,"1":5,"2":5,"3":5,"4":1,"5":1,"6":2,"7":1},"f":{"0":5,"1":5,"2":1,"3":1,"4":1},"b":{}} +,"/Users/viricel/Sites/fruit-project/src/components/Header.vue": {"path":"/Users/viricel/Sites/fruit-project/src/components/Header.vue","statementMap":{"0":{"start":{"line":28,"column":0},"end":{"line":28,"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":0},"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":32,"column":0},"end":{"line":32,"column":null}},"1":{"start":{"line":37,"column":0},"end":{"line":37,"column":null}},"2":{"start":{"line":58,"column":0},"end":{"line":58,"column":null}},"3":{"start":{"line":68,"column":0},"end":{"line":68,"column":null}},"4":{"start":{"line":69,"column":0},"end":{"line":77,"column":null}},"5":{"start":{"line":70,"column":0},"end":{"line":75,"column":null}},"6":{"start":{"line":73,"column":0},"end":{"line":73,"column":null}},"7":{"start":{"line":74,"column":0},"end":{"line":74,"column":null}},"8":{"start":{"line":75,"column":0},"end":{"line":75,"column":null}},"9":{"start":{"line":77,"column":0},"end":{"line":77,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":37,"column":0},"end":{"line":37,"column":null}},"loc":{"start":{"line":37,"column":0},"end":{"line":37,"column":null}}},"1":{"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}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":67,"column":0},"end":{"line":67,"column":null}},"loc":{"start":{"line":67,"column":0},"end":{"line":78,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":70,"column":0},"end":{"line":70,"column":null}},"loc":{"start":{"line":70,"column":0},"end":{"line":75,"column":null}}},"4":{"name":"(anonymous_6)","decl":{"start":{"line":75,"column":0},"end":{"line":75,"column":null}},"loc":{"start":{"line":75,"column":0},"end":{"line":75,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":69,"column":0},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":0},"end":{"line":77,"column":null}},{"start":{"line":69,"column":0},"end":{"line":77,"column":null}}]}},"s":{"0":1,"1":0,"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,"4":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":23,"column":0},"end":{"line":23,"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}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0},"f":{"0":0},"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":27,"column":0},"end":{"line":27,"column":null}},"2":{"start":{"line":36,"column":0},"end":{"line":36,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}},"loc":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":35,"column":0},"end":{"line":35,"column":null}},"loc":{"start":{"line":35,"column":0},"end":{"line":37,"column":null}}}},"branchMap":{},"s":{"0":1,"1":0,"2":2},"f":{"0":0,"1":2},"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":32,"column":0},"end":{"line":32,"column":null}},"2":{"start":{"line":34,"column":0},"end":{"line":34,"column":null}},"3":{"start":{"line":40,"column":0},"end":{"line":40,"column":null}},"4":{"start":{"line":46,"column":0},"end":{"line":46,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":32,"column":0},"end":{"line":32,"column":null}},"loc":{"start":{"line":32,"column":0},"end":{"line":32,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":33,"column":0},"end":{"line":33,"column":null}},"loc":{"start":{"line":33,"column":0},"end":{"line":37,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":39,"column":0},"end":{"line":39,"column":null}},"loc":{"start":{"line":39,"column":0},"end":{"line":41,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":45,"column":0},"end":{"line":45,"column":null}},"loc":{"start":{"line":45,"column":0},"end":{"line":47,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":46,"column":0},"end":{"line":46,"column":null}},"type":"cond-expr","locations":[{"start":{"line":46,"column":0},"end":{"line":46,"column":null}},{"start":{"line":46,"column":0},"end":{"line":46,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0},"f":{"0":0,"1":0,"2":0,"3":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":17,"column":0},"end":{"line":17,"column":null}},"2":{"start":{"line":22,"column":0},"end":{"line":22,"column":null}},"3":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":17,"column":0},"end":{"line":17,"column":null}},"loc":{"start":{"line":17,"column":0},"end":{"line":17,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":21,"column":0},"end":{"line":21,"column":null}},"loc":{"start":{"line":21,"column":0},"end":{"line":25,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":26,"column":0},"end":{"line":26,"column":null}},"loc":{"start":{"line":26,"column":0},"end":{"line":28,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}},"loc":{"start":{"line":27,"column":0},"end":{"line":27,"column":null}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{}} +} diff --git a/coverage/lcov-report/Fruits.vue.html b/coverage/lcov-report/Fruits.vue.html new file mode 100644 index 0000000..3ceea50 --- /dev/null +++ b/coverage/lcov-report/Fruits.vue.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for Fruits.vue + + + + + + + + +
+
+

All files Fruits.vue

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

+ 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  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  + 
<template>
+  <div>
+    <h1>Fruits Directory</h1>
+    {{ this.fruits }}
+  </div>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+ 
+export default {
+  name: "Fruits",
+  computed: {
+    ...mapState(["fruits"])
+  },
+  async created() {
+    await this.$store.dispatch("getFruits");
+  }
+};
+</script>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css new file mode 100644 index 0000000..f418035 --- /dev/null +++ b/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js new file mode 100644 index 0000000..c7ff5a5 --- /dev/null +++ b/coverage/lcov-report/block-navigation.js @@ -0,0 +1,79 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/components/AddFruit.vue.html b/coverage/lcov-report/components/AddFruit.vue.html new file mode 100644 index 0000000..f0b2917 --- /dev/null +++ b/coverage/lcov-report/components/AddFruit.vue.html @@ -0,0 +1,721 @@ + + + + + + Code coverage report for components/AddFruit.vue + + + + + + + + +
+
+

All files / components AddFruit.vue

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

+ 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 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +5x +  +  +  +  +  +  +  +5x +5x +  +  +1x +  +  +  +1x +2x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div class="modal">
+    <h2>New Fruit</h2>
+    <form id="new-fruit" @submit.prevent="checkForm">
+      <!-- name -->
+      <div class="form-field">
+        <label for="fruit-name">Name</label>
+        <input
+          id="fruit-name"
+          ref="autofocus"
+          type="text"
+          v-model="fruit.name"
+          placeholder="Ex: Banana"
+          required
+        />
+      </div>
+ 
+      <!-- image finder (with Unsplash API) -->
+      <ImageUnsplash
+        @getValue="url => (fruit.image = url)"
+        label="Image"
+        containerClass="form-field"
+        placeholder="Search: strawberry, apple ..."
+        :required="true"
+      />
+ 
+      <div class="form-group">
+        <!-- taste -->
+        <div class="form-field">
+          <label for="fruit-taste">Taste</label>
+          <input
+            id="fruit-taste"
+            type="text"
+            v-model="fruit.taste"
+            placeholder="Ex: sweet"
+            required
+          />
+        </div>
+ 
+        <!-- color -->
+        <div class="form-field">
+          <label for="fruit-color">Color</label>
+          <input id="fruit-color" type="color" v-model="fruit.color" placeholder="Color" required />
+        </div>
+      </div>
+ 
+      <div class="form-group">
+        <!-- price -->
+        <div class="form-field">
+          <label for="fruit-price">Price ($)</label>
+          <input
+            id="fruit-price"
+            type="number"
+            v-model="fruit.price"
+            placeholder="Ex: $13"
+            required
+            min="0"
+          />
+        </div>
+ 
+        <!-- expires -->
+        <div class="form-field">
+          <label for="fruit-expires">Expiration Date</label>
+          <input id="fruit-expires" type="date" v-model="fruit.expires" required />
+        </div>
+      </div>
+ 
+      <!-- description -->
+      <div class="form-field">
+        <label for="fruit-description">Description</label>
+        <textarea
+          id="fruit-description"
+          v-model="fruit.description"
+          placeholder="Ex: malesuada pellentesque elit eget ..."
+          required
+        />
+      </div>
+ 
+      <div class="actions">
+        <button class="btn btn--cancel" type="button" @click="() => $store.commit('toggleModal')">
+          Cancel
+        </button>
+        <button class="btn btn--success" type="submit">Save</button>
+      </div>
+    </form>
+  </div>
+</template>
+ 
+<script>
+import ImageUnsplash from "./Form/ImageUnsplash/ImageUnsplash";
+ 
+export default {
+  name: "AddFruit",
+  components: { ImageUnsplash },
+  data() {
+    return {
+      fruit: {
+        color: "#000000",
+        isFruit: true
+      }
+    };
+  },
+  mounted() {
+    this.$refs["autofocus"].focus();
+    document.body.classList.add("is-overlayed");
+  },
+  destroyed() {
+    document.body.classList.remove("is-overlayed");
+  },
+  methods: {
+    async checkForm(e) {
+      this.fruit.expires = new Date(this.fruit.expires);
+      await this.$store
+        .dispatch("addFruit", this.fruit)
+        .then(() => this.$store.commit("toggleModal"));
+      e.preventDefault();
+    }
+  }
+};
+</script>
+ 
+<style lang="less">
+.modal {
+  position: fixed;
+  top: @headerHeight;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: @color-2;
+  padding: 1rem;
+  z-index: 14;
+  overflow-y: scroll;
+ 
+  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;
+    margin-bottom: 1rem;
+ 
+    @media screen and (min-width: @sm) {
+      width: 425px;
+      margin: 0 auto 2rem auto;
+    }
+ 
+    [type="color"] {
+      height: 48px;
+    }
+ 
+    .form-field {
+      padding: 0.75rem 1rem;
+      border-radius: 4px;
+      box-sizing: border-box;
+      background-color: @color-2;
+      margin: 1rem 0;
+ 
+      label {
+        display: block;
+        font-weight: bold;
+        margin-bottom: 0.5rem;
+      }
+ 
+      textarea,
+      input {
+        width: 100%;
+        box-sizing: border-box;
+        border: none;
+        border-radius: 4px;
+        background-color: lighten(@text-color, 70%);
+        padding: 0.75rem 1rem;
+        color: darken(@color-1, 20%);
+      }
+    }
+ 
+    .form-group {
+      display: flex;
+      align-items: center;
+      margin: 1rem 0;
+      background-color: @color-2;
+ 
+      .form-field {
+        background-color: none;
+        margin: 0;
+        width: 50%;
+      }
+    }
+ 
+    .actions {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+ 
+      .btn {
+        border: none;
+        border-radius: 4px;
+        color: @color-2;
+        padding: 0.5rem 1.35rem;
+        margin: 0 0.5rem;
+ 
+        &--success {
+          background-color: #2ecc71;
+        }
+ 
+        &--cancel {
+          background-color: darken(#cecece, 15%);
+        }
+      }
+    }
+  }
+}
+</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..9cfc10e --- /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

+
+ +
+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<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..308ed0d --- /dev/null +++ b/coverage/lcov-report/components/Form/ImageUnsplash/ImageUnsplash.vue.html @@ -0,0 +1,475 @@ + + + + + + Code coverage report for components/Form/ImageUnsplash/ImageUnsplash.vue + + + + + + + + +
+
+

All files / components/Form/ImageUnsplash ImageUnsplash.vue

+
+ +
+ 10% + Statements + 1/10 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 10% + Lines + 1/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 +127 +128 +129 +130 +131 +132 +133  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div :class="containerClass" 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"
+        :required="required"
+      />
+    </div>
+  </div>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+ 
+export default {
+  name: "ImageUnsplash",
+  components: {
+    ImageSkeleton: () => import("./ImageSkeleton")
+  },
+  props: {
+    containerClass: {
+      type: String,
+      default: null
+    },
+    label: {
+      type: String,
+      default: "Image (from Unsplash)"
+    },
+    placeholder: {
+      type: String,
+      default: "Type anything !"
+    },
+    required: {
+      type: Boolean,
+      default: false
+    }
+  },
+  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 {
+  .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.5rem;
+      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..4934036 --- /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

+
+ +
+ 9.09% + Statements + 1/11 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 9.09% + Lines + 1/11 +
+ + +
+

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

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

All files / components Grid.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  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div class="grid">
+    <GridItem :key="item.id" v-for="item in data" :item="item" />
+  </div>
+</template>
+ 
+<script>
+import GridItem from "./GridItem";
+ 
+export default {
+  name: "Grid",
+  components: {
+    GridItem
+  },
+  props: {
+    data: Array
+  }
+};
+</script>
+ 
+<style scoped lang="less">
+.grid {
+  display: grid;
+  grid-template-columns: 1fr;
+  column-gap: 1rem;
+  row-gap: 1.5rem;
+ 
+  @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);
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ 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..9be1967 --- /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;
+ 
+    &--success {
+      background-color: #2ecc71;
+    }
+ 
+    &--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..f6bf5b3 --- /dev/null +++ b/coverage/lcov-report/components/Grid/Grid.vue.html @@ -0,0 +1,325 @@ + + + + + + Code coverage report for components/Grid/Grid.vue + + + + + + + + +
+
+

All files / components/Grid Grid.vue

+
+ +
+ 0% + Statements + 0/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<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";
+ 
+export default {
+  name: "Grid",
+  components: {
+    GridItemSkeleton,
+    GridItem: () => import("./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..5a15a7c --- /dev/null +++ b/coverage/lcov-report/components/Grid/GridItem.vue.html @@ -0,0 +1,409 @@ + + + + + + Code coverage report for components/Grid/GridItem.vue + + + + + + + + +
+
+

All files / components/Grid GridItem.vue

+
+ +
+ 66.67% + Statements + 2/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 66.67% + Lines + 2/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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<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";
+ 
+export default {
+  name: "GridItem",
+  components: { DeleteItem: () => import("./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..8efda22 --- /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..9a19fb8 --- /dev/null +++ b/coverage/lcov-report/components/Grid/index.html @@ -0,0 +1,155 @@ + + + + + + Code coverage report for components/Grid + + + + + + + + +
+
+

All files components/Grid

+
+ +
+ 20% + Statements + 2/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 20% + Lines + 2/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/00%0/10%0/3
GridItem.vue +
+
66.67%2/3100%0/050%1/266.67%2/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..429458d --- /dev/null +++ b/coverage/lcov-report/components/Header.vue.html @@ -0,0 +1,394 @@ + + + + + + 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 +103 +104 +105 +106  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +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
+        :disabled="modalIsOpen"
+        class="action-btn action-btn--delete"
+        @click="() => $store.commit('toggleDeleteMode')"
+      >
+        {{ deleteMode ? "&#x1F6AB;" : "&#x1f5d1;" }}
+      </button>
+      <button
+        :disabled="deleteMode"
+        class="action-btn action-btn--add"
+        @click="() => $store.commit('toggleModal')"
+      >
+        {{ modalIsOpen ? "&#x1F6AB;" : "&#x2795;" }}
+      </button>
+    </div>
+  </header>
+</template>
+ 
+<script>
+import { mapState } from "vuex";
+ 
+export default {
+  name: "Header",
+  computed: {
+    ...mapState(["deleteMode", "modalIsOpen"])
+  }
+};
+</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: 24px;
+        font-weight: lighter;
+        text-align: center;
+        margin-left: 1rem;
+        padding-top: 2px;
+        background: lighten(#cecece, 10%);
+ 
+        &:disabled {
+          opacity: 0.4;
+        }
+ 
+        &--delete {
+          border: 1px solid @text-error;
+        }
+ 
+        &--add {
+          border: 1px solid @color-1;
+        }
+      }
+    }
+  }
+}
+</style>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/components/index.html b/coverage/lcov-report/components/index.html new file mode 100644 index 0000000..049cf53 --- /dev/null +++ b/coverage/lcov-report/components/index.html @@ -0,0 +1,125 @@ + + + + + + Code coverage report for components + + + + + + + + +
+
+

All files components

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

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

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
AddFruit.vue +
+
100%8/8100%0/0100%5/5100%8/8
Header.vue +
+
100%1/1100%0/0100%0/0100%1/1
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html new file mode 100644 index 0000000..65c74b7 --- /dev/null +++ b/coverage/lcov-report/index.html @@ -0,0 +1,155 @@ + + + + + + Code coverage report for All files + + + + + + + + +
+
+

All files

+
+ +
+ 30.77% + Statements + 12/39 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 23.08% + Functions + 6/26 +
+ + +
+ 30.77% + Lines + 12/39 +
+ + +
+

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

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
components +
+
100%9/9100%0/0100%5/5100%9/9
components/Form/ImageUnsplash +
+
9.09%1/110%0/20%0/59.09%1/11
components/Grid +
+
20%2/10100%0/012.5%1/820%2/10
views +
+
0%0/90%0/20%0/80%0/9
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..b317a7c --- /dev/null +++ b/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..b322523 --- /dev/null +++ b/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000..03f704a Binary files /dev/null and b/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..16de10c --- /dev/null +++ b/coverage/lcov-report/sorter.js @@ -0,0 +1,170 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/lcov-report/store/index.html b/coverage/lcov-report/store/index.html new file mode 100644 index 0000000..3dd2305 --- /dev/null +++ b/coverage/lcov-report/store/index.html @@ -0,0 +1,110 @@ + + + + + + Code coverage report for store + + + + + + + + +
+
+

All files store

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

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

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js +
+
50%1/2100%0/00%0/150%1/2
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/store/index.js.html b/coverage/lcov-report/store/index.js.html new file mode 100644 index 0000000..000525a --- /dev/null +++ b/coverage/lcov-report/store/index.js.html @@ -0,0 +1,130 @@ + + + + + + Code coverage report for store/index.js + + + + + + + + +
+
+

All files / store index.js

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

+ 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  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import Vue from "vue";
+import Vuex from "vuex";
+ 
+Vue.use(Vuex);
+ 
+export default new Vuex.Store({
+  state: {
+    fruits: []
+  },
+  mutations: {
+    setFruits(state, fruits) {
+      state.fruits = fruits;
+    }
+  },
+  actions: {},
+  modules: {}
+});
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/views/Fruit.vue.html b/coverage/lcov-report/views/Fruit.vue.html new file mode 100644 index 0000000..b201c40 --- /dev/null +++ b/coverage/lcov-report/views/Fruit.vue.html @@ -0,0 +1,499 @@ + + + + + + Code coverage report for views/Fruit.vue + + + + + + + + +
+
+

All files / views Fruit.vue

+
+ +
+ 0% + Statements + 0/5 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 0% + Lines + 0/5 +
+ + +
+

+ 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 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div>
+    <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";
+ 
+export default {
+  name: "FruitDetails",
+  components: { DeleteItem: () => import("@/components/Grid/DeleteItem") },
+  data() {
+    return {
+      modalOpen: true
+    };
+  },
+  filters: {
+    noDecimal(value) {
+      return parseInt(value).toFixed();
+    }
+  },
+  computed: {
+    ...mapState(["fruit", "deleteMode"]),
+    expirationState() {
+      return new Date(this.fruit.expires) < new Date() ? "expired" : "expires";
+    }
+  }
+};
+</script>
+ 
+<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>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/views/Fruits.vue.html b/coverage/lcov-report/views/Fruits.vue.html new file mode 100644 index 0000000..e009398 --- /dev/null +++ b/coverage/lcov-report/views/Fruits.vue.html @@ -0,0 +1,265 @@ + + + + + + Code coverage report for views/Fruits.vue + + + + + + + + +
+
+

All files / views Fruits.vue

+
+ +
+ 0% + Statements + 0/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/4 +
+ + +
+ 0% + Lines + 0/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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
<template>
+  <div class="fruits">
+    <h2>Directory</h2>
+    <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";
+ 
+export default {
+  name: "Fruits",
+  components: { Grid: () => import("@/components/Grid/Grid") },
+  computed: {
+    ...mapState(["fruits"])
+  },
+  data() {
+    return {
+      error: null
+    };
+  },
+  async created() {
+    await this.$store.dispatch("getFruits").catch(err => (this.error = err));
+  }
+};
+</script>
+ 
+<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>
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov-report/views/index.html b/coverage/lcov-report/views/index.html new file mode 100644 index 0000000..963e571 --- /dev/null +++ b/coverage/lcov-report/views/index.html @@ -0,0 +1,125 @@ + + + + + + Code coverage report for views + + + + + + + + +
+
+

All files views

+
+ +
+ 0% + Statements + 0/9 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/8 +
+ + +
+ 0% + Lines + 0/9 +
+ + +
+

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

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
Fruit.vue +
+
0%0/50%0/20%0/40%0/5
Fruits.vue +
+
0%0/4100%0/00%0/40%0/4
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 0000000..114320f --- /dev/null +++ b/coverage/lcov.info @@ -0,0 +1,185 @@ +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/AddFruit.vue +FN:95,(anonymous_1) +FN:103,(anonymous_2) +FN:107,(anonymous_3) +FN:111,(anonymous_4) +FN:113,(anonymous_5) +FNF:5 +FNH:5 +FNDA:5,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:1,(anonymous_5) +DA:90,1 +DA:96,5 +DA:104,5 +DA:105,5 +DA:108,1 +DA:112,1 +DA:113,2 +DA:116,1 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Header.vue +FNF:0 +FNH:0 +DA:28,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageSkeleton.vue +FNF:0 +FNH:0 +DA:13,0 +LF:1 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/components/Form/ImageUnsplash/ImageUnsplash.vue +FN:37,(anonymous_1) +FN:57,(anonymous_3) +FN:67,(anonymous_4) +FN:70,(anonymous_5) +FN:75,(anonymous_6) +FNF:5 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:32,1 +DA:37,0 +DA:58,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:77,0 +LF:10 +LH:1 +BRDA:69,0,0,0 +BRDA:69,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 +FN:23,(anonymous_1) +FNF:1 +FNH:0 +FNDA:0,(anonymous_1) +DA:16,0 +DA:17,0 +DA:23,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:27,(anonymous_1) +FN:35,(anonymous_3) +FNF:2 +FNH:1 +FNDA:0,(anonymous_1) +FNDA:2,(anonymous_3) +DA:23,1 +DA:27,0 +DA:36,2 +LF:3 +LH:2 +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/Fruit.vue +FN:32,(anonymous_1) +FN:33,(anonymous_3) +FN:39,(anonymous_4) +FN:45,(anonymous_5) +FNF:4 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:28,0 +DA:32,0 +DA:34,0 +DA:40,0 +DA:46,0 +LF:5 +LH:0 +BRDA:46,0,0,0 +BRDA:46,0,1,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:/Users/viricel/Sites/fruit-project/src/views/Fruits.vue +FN:17,(anonymous_1) +FN:21,(anonymous_3) +FN:26,(anonymous_4) +FN:27,(anonymous_5) +FNF:4 +FNH:0 +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:13,0 +DA:17,0 +DA:22,0 +DA:27,0 +LF:4 +LH:0 +BRF:0 +BRH:0 +end_of_record diff --git a/cypress.json b/cypress.json new file mode 100644 index 0000000..470c720 --- /dev/null +++ b/cypress.json @@ -0,0 +1,3 @@ +{ + "pluginsFile": "tests/e2e/plugins/index.js" +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..268a513 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,15 @@ +module.exports = { + preset: "@vue/cli-plugin-unit-jest", + moduleNameMapper: { + "^@/(.*)$": "/src/$1", + "^~/(.*)$": "/src/$1", + "^vue$": "vue/dist/vue.common.js" + }, + moduleFileExtensions: ["js", "vue", "json"], + transform: { + "^.+\\.js$": "babel-jest", + ".*\\.(vue)$": "vue-jest" + }, + collectCoverage: true, + collectCoverageFrom: ["/src/components/**/*.vue", "/src/views/**/*.vue"] +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..d02831d --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "fruit-project", + "description": "A test project for Cycloid.io.", + "version": "0.1.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "test:unit": "vue-cli-service test:unit", + "test:e2e": "vue-cli-service test:e2e", + "lint": "vue-cli-service lint", + "api": "fruit-api" + }, + "dependencies": { + "axios": "^0.21.0", + "core-js": "^3.6.5", + "fruit-api": "^1.1.3", + "vue": "^2.6.11", + "vue-content-loading": "^1.6.0", + "vue-moment": "^4.1.0", + "vue-router": "^3.2.0", + "vuex": "^3.4.0" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "~4.5.0", + "@vue/cli-plugin-e2e-cypress": "~4.5.0", + "@vue/cli-plugin-eslint": "~4.5.0", + "@vue/cli-plugin-router": "~4.5.0", + "@vue/cli-plugin-unit-jest": "~4.5.0", + "@vue/cli-plugin-vuex": "~4.5.0", + "@vue/cli-service": "~4.5.0", + "@vue/test-utils": "^1.0.3", + "babel-eslint": "^10.1.0", + "eslint": "^6.7.2", + "eslint-config-prettier": "^6.15.0", + "eslint-plugin-import": "^2.20.2", + "eslint-plugin-prettier": "^3.2.0", + "eslint-plugin-vue": "^6.2.2", + "less": "^3.12.2", + "less-loader": "^7.1.0", + "vue-template-compiler": "^2.6.11" + } +} diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..75ae215 --- /dev/null +++ b/public/_redirects @@ -0,0 +1,2 @@ +# Netlify settings for single-page application +/* /index.html 200 \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..43820e7 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..4123528 --- /dev/null +++ b/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + +
+ + + diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..13be9b5 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/assets/less/reset.less b/src/assets/less/reset.less new file mode 100644 index 0000000..7708b7a --- /dev/null +++ b/src/assets/less/reset.less @@ -0,0 +1,293 @@ +/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ + +// * 1. Set default font family to sans-serif. +// * 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} + +// Remove default margin. +body { + margin: 0; +} + +// HTML5 display definitions ========================================================================== +// * Correct `block` display not defined for any HTML5 element in IE 8/9. +// * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. +// * Correct `block` display not defined for `main` in IE 11. +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +// * 1. Correct `inline-block` display not defined in IE 8/9. +// * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} + +// * Prevent modern browsers from displaying `audio` without controls. +// * Remove excess height in iOS 5 devices. +audio:not([controls]) { + display: none; + height: 0; +} + +// * Address `[hidden]` styling not present in IE 8/9/10. +// * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. +[hidden], +template { + display: none; +} + +// Links ========================================================================== +// * Remove the gray background color from active links in IE 10. +a { + background: transparent; + // * Improve readability when focused and also mouse hovered in all browsers. + &:active, + &:hover { + outline: 0; + } +} + +// Text-level semantics ========================================================================== + +// * Address styling not present in IE 8/9/10/11, Safari, and Chrome. +abbr[title] { + border-bottom: 1px dotted; +} + +// * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. +b, +strong { + font-weight: bold; +} + +// * Address styling not present in Safari and Chrome. +dfn { + font-style: italic; +} + +// * Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari, and Chrome. +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +// * Address styling not present in IE 8/9. +mark { + background: #ff0; + color: #000; +} + +// * Address inconsistent and variable font size in all browsers. +small { + font-size: 80%; +} + +// * Prevent `sub` and `sup` affecting `line-height` in all browsers. +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} + +// Embedded content ========================================================================== +// * Remove border when inside `a` element in IE 8/9/10. +img { + border: 0; +} + +// * Correct overflow not hidden in IE 9/10/11. +svg:not(:root) { + overflow: hidden; +} + +// Grouping content ========================================================================== +// * Address margin not present in IE 8/9 and Safari. +figure { + margin: 1em 40px; +} + +// * Address differences between Firefox and other browsers. +hr { + box-sizing: content-box; + height: 0; +} + +// * Contain overflow in all browsers. +pre { + overflow: auto; +} + +// * Address odd `em`-unit font size rendering in all browsers. +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +// Forms ========================================================================== +// * Known limitation: by default, Chrome and Safari on OS X allow very limited +// * styling of `select`, unless a `border` property is set. + +// * 1. Correct color not being inherited. +// * Known issue: affects color of disabled elements. +// * 2. Correct font properties not being inherited. +// * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} + +// * Address `overflow` set to `hidden` in IE 8/9/10/11. +button { + overflow: visible; +} + +// * Address inconsistent `text-transform` inheritance for `button` and `select`. +// * All other form control elements do not inherit `text-transform` values. +// * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. +// * Correct `select` style inheritance in Firefox. +button, +select { + text-transform: none; +} + +// * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. +// * 2. Correct inability to style clickable `input` types in iOS. +// * 3. Improve usability and consistency of cursor style between image-type `input` and others. +button, +html input[type="button"] { + -webkit-appearance: button; + cursor: pointer; +} + +// * Re-set default cursor for disabled elements. +button[disabled], +html input[disabled] { + cursor: default; +} + +// * Remove inner padding and border in Firefox 4+. +button input { + &::-moz-focus-inner { + border: 0; + padding: 0; + } +} + +// * Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. +input { + line-height: normal; + &[type="reset"], + &[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + } + + // * It's recommended that you don't attempt to style these elements. + // * Firefox's implementation doesn't respect box-sizing, padding, or width. + // * 1. Address box sizing set to `content-box` in IE 8/9/10. + // * 2. Remove excess padding in IE 8/9/10. + &[type="checkbox"], + &[type="radio"] { + box-sizing: border-box; + padding: 0; + } + + // * Fix the cursor style for Chrome's increment/decrement buttons. For certain + // * `font-size` values of the `input`, it causes the cursor style of the + // * decrement button to change from `default` to `text`. + &[type="number"] { + &::-webkit-inner-spin-button, + &::-webkit-outer-spin-button { + height: auto; + } + } + + // * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + // * 2. Address `box-sizing` set to `border-box` in Safari and Chrome (include `-moz` to future-proof). + &[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; + + // * Remove inner padding and search cancel button in Safari and Chrome on OS X. + // * Safari (but not Chrome) clips the cancel button when the search input has + // * padding (and `textfield` appearance). + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + } +} + +// * Define consistent border, margin, and padding. +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +// * 1. Correct `color` not being inherited in IE 8/9/10/11. +// * 2. Remove padding so people aren't caught out if they zero out fieldsets. +legend { + border: 0; + padding: 0; +} + +// * Remove default vertical scrollbar in IE 8/9/10/11. +textarea { + overflow: auto; +} + +// * Don't inherit the `font-weight` (applied by a rule above). +// * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. +optgroup { + font-weight: bold; +} + +// Tables ========================================================================== +// * Remove most spacing between table cells. +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/src/assets/less/variables.less b/src/assets/less/variables.less new file mode 100644 index 0000000..9c2ef87 --- /dev/null +++ b/src/assets/less/variables.less @@ -0,0 +1,19 @@ +@color-1: #0c9696; +@color-2: #ffffff; +@color-3: #ff9700; +@text-color: #333; +@text-error: #d63031; + +@headerHeight: 58px; +@footerHeight: 58px; + +@sm: 640px; +// => @media (min-width: 640px) { ... } +@md: 768px; +// => @media (min-width: 768px) { ... } +@lg: 1024px; +// => @media (min-width: 1024px) { ... } +@xl: 1280px; +// => @media (min-width: 1280px) { ... } +@2xl: 1536px; +// => @media (min-width: 1536px) { ... } diff --git a/src/components/AddFruit.vue b/src/components/AddFruit.vue new file mode 100644 index 0000000..51d73f9 --- /dev/null +++ b/src/components/AddFruit.vue @@ -0,0 +1,214 @@ +