Browse Source

Basic OFF API implementation

Phyks (Lucas Verney) 2 years ago
parent
commit
762d2866b8
10 changed files with 115 additions and 10 deletions
  1. 10
    2
      .eslintrc.js
  2. 3
    2
      package.json
  3. 13
    0
      src/api/index.js
  4. 34
    6
      src/components/Product.vue
  5. 2
    0
      src/main.js
  6. 14
    0
      src/store/actions.js
  7. 4
    0
      src/store/getters.js
  8. 17
    0
      src/store/index.js
  9. 2
    0
      src/store/mutations-types.js
  10. 16
    0
      src/store/mutations.js

+ 10
- 2
.eslintrc.js View File

@@ -36,6 +36,14 @@ module.exports = {
36 36
     // allow debugger during development
37 37
     'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
38 38
     // Use 4 spaces indent
39
-    'indent': ['error', 4]
39
+    'indent': ['error', 4],
40
+    // Ignore assignment to state
41
+    'no-param-reassign': [
42
+        "error",
43
+        {
44
+            "props": true,
45
+            "ignorePropertyModificationsFor": ["state"]
46
+        }
47
+    ],
40 48
   }
41
-}
49
+};

+ 3
- 2
package.json View File

@@ -14,10 +14,11 @@
14 14
     "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
15 15
   },
16 16
   "dependencies": {
17
-    "quagga": "^0.12.1",
17
+    "es6-promise": "^4.1.1",
18
+    "isomorphic-fetch": "^2.2.1",
18 19
     "vue": "^2.4.2",
19 20
     "vue-router": "^2.7.0",
20
-    "webrtc-adapter": "^5.0.4"
21
+    "vuex": "^2.4.0"
21 22
   },
22 23
   "devDependencies": {
23 24
     "autoprefixer": "^7.1.2",

+ 13
- 0
src/api/index.js View File

@@ -0,0 +1,13 @@
1
+require('es6-promise').polyfill();
2
+require('isomorphic-fetch');
3
+
4
+/**
5
+ * TODO
6
+ */
7
+export default function (EAN) {
8
+    return fetch(
9
+        `https://world.openfoodfacts.org/api/v0/product/${EAN}.json`,
10
+    )
11
+        .then(response => response.json())
12
+        .catch(exc => console.error(`Unable to fetch product: ${exc}.`));
13
+}

+ 34
- 6
src/components/Product.vue View File

@@ -1,13 +1,41 @@
1 1
 <template>
2
-    <table>
3
-        <tr>
4
-            <th>Barcode</th>
5
-            <td>{{ $route.params.barcode }}</td>
6
-        </tr>
7
-    </table>
2
+    <div>
3
+        <template v-if="isLoading">
4
+            <p>Loading…</p>
5
+        </template>
6
+        <template v-else>
7
+            <h2>{{ this.product.product_name }}</h2>
8
+            <table>
9
+                <tr>
10
+                    <th>Barcode</th>
11
+                    <td>{{ $route.params.barcode }}</td>
12
+                </tr>
13
+            </table>
14
+        </template>
15
+    </div>
8 16
 </template>
9 17
 
10 18
 <script>
11 19
 export default {
20
+    created() {
21
+        this.fetchData();
22
+    },
23
+    watch: {
24
+        // Fetch again when the component is updated
25
+        $route: 'fetchData',
26
+    },
27
+    computed: {
28
+        product() {
29
+            return this.$store.getters.product;
30
+        },
31
+        isLoading() {
32
+            return this.$store.getters.isLoading;
33
+        },
34
+    },
35
+    methods: {
36
+        fetchData() {
37
+            this.$store.dispatch('getProduct', { EAN: this.$route.params.barcode });
38
+        },
39
+    },
12 40
 };
13 41
 </script>

+ 2
- 0
src/main.js View File

@@ -3,6 +3,7 @@
3 3
 import Vue from 'vue';
4 4
 import App from './App';
5 5
 import router from './router';
6
+import store from './store';
6 7
 
7 8
 Vue.config.productionTip = false;
8 9
 
@@ -10,6 +11,7 @@ Vue.config.productionTip = false;
10 11
 new Vue({
11 12
     el: '#app',
12 13
     router,
14
+    store,
13 15
     template: '<App/>',
14 16
     components: { App },
15 17
 });

+ 14
- 0
src/store/actions.js View File

@@ -0,0 +1,14 @@
1
+import getProduct from '@/api';
2
+import * as types from './mutations-types';
3
+
4
+export default {
5
+    getProduct({ commit }, { EAN }) {
6
+        commit(types.IS_LOADING);
7
+        getProduct(EAN).then(
8
+            (result) => {
9
+                const { product } = result;
10
+                commit(types.STORE_PRODUCT, { product });
11
+            },
12
+        );
13
+    },
14
+};

+ 4
- 0
src/store/getters.js View File

@@ -0,0 +1,4 @@
1
+export default {
2
+    product: state => state.product,
3
+    isLoading: state => state.isLoading,
4
+};

+ 17
- 0
src/store/index.js View File

@@ -0,0 +1,17 @@
1
+import Vue from 'vue';
2
+import Vuex from 'vuex';
3
+import createLogger from 'vuex/dist/logger';  // TODO
4
+
5
+import actions from './actions';
6
+import getters from './getters';
7
+import { initialState as state, mutations } from './mutations';
8
+
9
+Vue.use(Vuex);
10
+
11
+export default new Vuex.Store({
12
+    state,
13
+    actions,
14
+    getters,
15
+    mutations,
16
+    plugins: [createLogger()],
17
+});

+ 2
- 0
src/store/mutations-types.js View File

@@ -0,0 +1,2 @@
1
+export const IS_LOADING = 'IS_LOADING';
2
+export const STORE_PRODUCT = 'STORE_PRODUCT';

+ 16
- 0
src/store/mutations.js View File

@@ -0,0 +1,16 @@
1
+import * as types from './mutations-types';
2
+
3
+export const initialState = {
4
+    product: null,
5
+    isLoading: false,
6
+};
7
+
8
+export const mutations = {
9
+    [types.STORE_PRODUCT](state, { product }) {
10
+        state.product = product;
11
+        state.isLoading = false;
12
+    },
13
+    [types.IS_LOADING](state) {
14
+        state.isLoading = true;
15
+    },
16
+};