Browse Source

Beginning of a Material UI

Phyks (Lucas Verney) 2 years ago
parent
commit
1cf5ca992a

+ 2
- 1
index.html View File

@@ -3,7 +3,8 @@
3 3
     <head>
4 4
         <meta charset="utf-8">
5 5
         <title>Food</title>
6
-        <meta name="viewport" content="width=device-width, user-scalable=no">
6
+        <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
7
+        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
7 8
     </head>
8 9
     <body>
9 10
         <div id="app"></div>

+ 1
- 0
package.json View File

@@ -18,6 +18,7 @@
18 18
     "isomorphic-fetch": "^2.2.1",
19 19
     "vue": "^2.4.2",
20 20
     "vue-router": "^2.7.0",
21
+    "vuetify": "^0.15.7",
21 22
     "vuex": "^2.4.0"
22 23
   },
23 24
   "devDependencies": {

+ 32
- 13
src/App.vue View File

@@ -1,23 +1,42 @@
1 1
 <template>
2
-    <div id="app">
3
-        <h1>Food scanning</h1>
4
-        <router-view></router-view>
5
-    </div>
2
+    <v-app toolbar>
3
+        <NavigationDrawer :isDrawerVisible="isDrawerVisible"/>
4
+        <v-toolbar class="indigo" dark>
5
+            <v-toolbar-side-icon @click.stop="showHideDrawer"></v-toolbar-side-icon>
6
+            <v-toolbar-title>{{ title }}</v-toolbar-title>
7
+        </v-toolbar>
8
+        <main>
9
+            <v-container fluid>
10
+                <router-view></router-view>
11
+            </v-container>
12
+        </main>
13
+    </v-app>
6 14
 </template>
7 15
 
8 16
 <script>
17
+import NavigationDrawer from '@/components/NavigationDrawer';
18
+
9 19
 export default {
10
-    name: 'app',
20
+    components: {
21
+        NavigationDrawer,
22
+    },
23
+    computed: {
24
+        title() {
25
+            return this.$store.getters.title;
26
+        },
27
+    },
28
+    data() {
29
+        return {
30
+            isDrawerVisible: false,
31
+        };
32
+    },
33
+    methods: {
34
+        showHideDrawer() {
35
+            this.isDrawerVisible = !this.isDrawerVisible;
36
+        },
37
+    },
11 38
 };
12 39
 </script>
13 40
 
14 41
 <style>
15
-#app {
16
-    font-family: 'Avenir', Helvetica, Arial, sans-serif;
17
-    -webkit-font-smoothing: antialiased;
18
-    -moz-osx-font-smoothing: grayscale;
19
-    text-align: center;
20
-    color: #2c3e50;
21
-    margin-top: 60px;
22
-}
23 42
 </style>

+ 0
- 12
src/components/Home.vue View File

@@ -1,12 +0,0 @@
1
-<template>
2
-    <nav>
3
-        <ul>
4
-            <router-link to="scan">Scan something!</router-link>
5
-        </ul>
6
-    </nav>
7
-</template>
8
-
9
-<script>
10
-export default {
11
-};
12
-</script>

+ 51
- 0
src/components/NavigationDrawer.vue View File

@@ -0,0 +1,51 @@
1
+<template>
2
+    <v-navigation-drawer
3
+        persistent
4
+        clipped
5
+        enable-resize-watcher
6
+        v-model="isDrawerVisible"
7
+        >
8
+        <v-list>
9
+            <v-list-tile :to="{ name: 'Home' }" exact>
10
+                <v-list-tile-action>
11
+                    <v-icon>home</v-icon>
12
+                </v-list-tile-action>
13
+                <v-list-tile-content>
14
+                    <v-list-tile-title>Home</v-list-tile-title>
15
+                </v-list-tile-content>
16
+            </v-list-tile>
17
+            <v-list-tile :to="{ name: 'Scan' }">
18
+                <v-list-tile-action>
19
+                    <v-icon>search</v-icon>
20
+                </v-list-tile-action>
21
+                <v-list-tile-content>
22
+                    <v-list-tile-title>Scan</v-list-tile-title>
23
+                </v-list-tile-content>
24
+            </v-list-tile>
25
+            <v-list-tile :to="{ name: 'ManualBarcode' }">
26
+                <v-list-tile-action>
27
+                    <v-icon>search</v-icon>
28
+                </v-list-tile-action>
29
+                <v-list-tile-content>
30
+                    <v-list-tile-title>Find by barcode</v-list-tile-title>
31
+                </v-list-tile-content>
32
+            </v-list-tile>
33
+            <v-list-tile :to="{ name: 'Preferences' }">
34
+                <v-list-tile-action>
35
+                    <v-icon>settings</v-icon>
36
+                </v-list-tile-action>
37
+                <v-list-tile-content>
38
+                    <v-list-tile-title>Preferences</v-list-tile-title>
39
+                </v-list-tile-content>
40
+            </v-list-tile>
41
+        </v-list>
42
+    </v-navigation-drawer>
43
+</template>
44
+
45
+<script>
46
+export default {
47
+    props: {
48
+        isDrawerVisible: Boolean,
49
+    },
50
+};
51
+</script>

+ 0
- 41
src/components/Product.vue View File

@@ -1,41 +0,0 @@
1
-<template>
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>
16
-</template>
17
-
18
-<script>
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
-    },
40
-};
41
-</script>

+ 4
- 0
src/main.js View File

@@ -1,12 +1,16 @@
1 1
 // The Vue build version to load with the `import` command
2 2
 // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 3
 import Vue from 'vue';
4
+import Vuetify from 'vuetify';
5
+import '../node_modules/vuetify/dist/vuetify.min.css';
4 6
 import App from './App';
5 7
 import router from './router';
6 8
 import store from './store';
7 9
 
8 10
 Vue.config.productionTip = false;
9 11
 
12
+Vue.use(Vuetify);
13
+
10 14
 /* eslint-disable no-new */
11 15
 new Vue({
12 16
     el: '#app',

+ 15
- 3
src/router/index.js View File

@@ -1,9 +1,11 @@
1 1
 import Vue from 'vue';
2 2
 import Router from 'vue-router';
3 3
 
4
-import Home from '@/components/Home';
5
-import Scan from '@/components/Scan';
6
-import Product from '@/components/Product';
4
+import Home from '@/views/Home';
5
+import ManualBarcode from '@/views/ManualBarcode';
6
+import Scan from '@/views/Scan';
7
+import Product from '@/views/Product';
8
+import Preferences from '@/views/Preferences';
7 9
 
8 10
 Vue.use(Router);
9 11
 
@@ -20,9 +22,19 @@ export default new Router({
20 22
             component: Scan,
21 23
         },
22 24
         {
25
+            path: '/barcode',
26
+            name: 'ManualBarcode',
27
+            component: ManualBarcode,
28
+        },
29
+        {
23 30
             path: '/barcode/:barcode',
24 31
             name: 'Product',
25 32
             component: Product,
26 33
         },
34
+        {
35
+            path: '/preferences',
36
+            name: 'Preferences',
37
+            component: Preferences,
38
+        },
27 39
     ],
28 40
 });

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

@@ -11,4 +11,7 @@ export default {
11 11
             },
12 12
         );
13 13
     },
14
+    setTitle({ commit }, { title }) {
15
+        commit(types.SET_TITLE, { title });
16
+    },
14 17
 };

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

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

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

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

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

@@ -3,6 +3,7 @@ import * as types from './mutations-types';
3 3
 export const initialState = {
4 4
     product: null,
5 5
     isLoading: false,
6
+    title: 'Food scanning',
6 7
 };
7 8
 
8 9
 export const mutations = {
@@ -13,4 +14,7 @@ export const mutations = {
13 14
     [types.IS_LOADING](state) {
14 15
         state.isLoading = true;
15 16
     },
17
+    [types.SET_TITLE](state, { title }) {
18
+        state.title = title;
19
+    },
16 20
 };

+ 23
- 0
src/views/Home.vue View File

@@ -0,0 +1,23 @@
1
+<template>
2
+    <div>
3
+        <h2>Let's start scanning!</h2>
4
+        <v-btn
5
+            dark
6
+            fab
7
+            fixed
8
+            bottom
9
+            right
10
+            class="pink"
11
+            >
12
+            <v-icon>search</v-icon>
13
+        </v-btn>
14
+    </div>
15
+</template>
16
+
17
+<script>
18
+export default {
19
+    created() {
20
+        this.$store.dispatch('setTitle', { title: 'Food scanning' });
21
+    },
22
+};
23
+</script>

+ 40
- 0
src/views/ManualBarcode.vue View File

@@ -0,0 +1,40 @@
1
+<template>
2
+    <v-form v-model="valid" ref="form">
3
+        <v-text-field
4
+            label="EAN13 barcode"
5
+            v-model="ean13"
6
+            :rules="ean13Rules"
7
+            :counter="13"
8
+            type="number"
9
+            required
10
+            ></v-text-field>
11
+        <p class="text-xs-right">
12
+            <v-btn @click="submit" :disabled="!valid" :class="{ green: valid }">Find</v-btn>
13
+        </p>
14
+    </v-form>
15
+</template>
16
+
17
+<script>
18
+export default {
19
+    created() {
20
+        this.$store.dispatch('setTitle', { title: 'Manual barcode' });
21
+    },
22
+    data() {
23
+        return {
24
+            valid: false,
25
+            ean13: '',
26
+            ean13Rules: [
27
+                v => !!v || 'EAN13 barcode is required.',
28
+                v => /^\d{13}$/.test(v) || 'EAN13 barcode is invalid.',
29
+            ],
30
+        };
31
+    },
32
+    methods: {
33
+        submit() {
34
+            if (this.$refs.form.validate()) {
35
+                this.$router.push({ name: 'Product', params: { barcode: this.ean13 } });
36
+            }
37
+        },
38
+    },
39
+};
40
+</script>

+ 11
- 0
src/views/Preferences.vue View File

@@ -0,0 +1,11 @@
1
+<template>
2
+    <p>TODO</p>
3
+</template>
4
+
5
+<script>
6
+export default {
7
+    created() {
8
+        this.$store.dispatch('setTitle', { title: 'Preferences' });
9
+    },
10
+};
11
+</script>

+ 72
- 0
src/views/Product.vue View File

@@ -0,0 +1,72 @@
1
+<template>
2
+    <v-flex class="text-xs-center">
3
+        <template v-if="isLoading">
4
+            <p>Loading…</p>
5
+        </template>
6
+        <template v-else>
7
+            <p><img :src="this.product.image_front_small_url"></p>
8
+            <v-tabs centered>
9
+                <v-tabs-items>
10
+                    <v-tabs-content id="tab-overview">
11
+                        <v-card flat>
12
+                            <v-card-text>
13
+                            </v-card-text>
14
+                        </v-card>
15
+                    </v-tabs-content>
16
+                    <v-tabs-content id="tab-nutrition">
17
+                        <v-card flat>
18
+                            <v-card-text>
19
+                                <v-data-table
20
+                                    hide-actions
21
+                                    >
22
+                                    <template slot="items" scope="props">
23
+                                        <td>{{ props.item.name }}</td>
24
+                                    </template>
25
+                                </v-data-table>
26
+                            </v-card-text>
27
+                        </v-card>
28
+                    </v-tabs-content>
29
+                    <v-tabs-content id="tab-labels">
30
+                        <v-card flat>
31
+                            <v-card-text>Bidule</v-card-text>
32
+                        </v-card>
33
+                    </v-tabs-content>
34
+                </v-tabs-items>
35
+                <v-tabs-bar class="cyan">
36
+                    <v-tabs-slider class="yellow"></v-tabs-slider>
37
+                    <v-tabs-item href="#tab-overview">Overview</v-tabs-item>
38
+                    <v-tabs-item href="#tab-nutrition">Nutrition</v-tabs-item>
39
+                    <v-tabs-item href="#tab-labels">Labels</v-tabs-item>
40
+                </v-tabs-bar>
41
+            </v-tabs>
42
+        </template>
43
+    </v-flex>
44
+</template>
45
+
46
+<script>
47
+export default {
48
+    created() {
49
+        this.$store.dispatch('setTitle', { title: 'Loading' });
50
+        this.fetchData();
51
+    },
52
+    watch: {
53
+        // Fetch again when the component is updated
54
+        $route: 'fetchData',
55
+    },
56
+    computed: {
57
+        product() {
58
+            const product = this.$store.getters.product;
59
+            this.$store.dispatch('setTitle', { title: product.product_name });
60
+            return product;
61
+        },
62
+        isLoading() {
63
+            return this.$store.getters.isLoading;
64
+        },
65
+    },
66
+    methods: {
67
+        fetchData() {
68
+            this.$store.dispatch('getProduct', { EAN: this.$route.params.barcode });
69
+        },
70
+    },
71
+};
72
+</script>

src/components/Scan.vue → src/views/Scan.vue View File


src/components/ScanQuagga.vue → src/views/ScanQuagga.vue View File