├── .browserslistrc ├── public ├── robots.txt ├── favicon.ico ├── img │ ├── bca.png │ ├── mandiri.png │ ├── unavailable.png │ └── icons │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-150x150.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── msapplication-icon-144x144.png │ │ └── safari-pinned-tab.svg ├── manifest.json └── index.html ├── babel.config.js ├── tests └── unit │ ├── .eslintrc.js │ └── example.spec.js ├── postcss.config.js ├── src ├── assets │ ├── logo.png │ └── logo.svg ├── plugins │ ├── vuetify.js │ ├── helper.js │ └── axios.js ├── main.js ├── stores │ ├── auth.js │ ├── alert.js │ ├── region.js │ ├── dialog.js │ └── cart.js ├── views │ ├── Profile.vue │ ├── About.vue │ ├── Books.vue │ ├── MyOrder.vue │ ├── Categories.vue │ ├── Category.vue │ ├── Payment.vue │ ├── Home.vue │ ├── Book.vue │ └── Checkout.vue ├── components │ ├── BookItem.vue │ ├── Alert.vue │ ├── Search.vue │ ├── Cart.vue │ ├── HelloWorld.vue │ ├── Login.vue │ └── Register.vue ├── registerServiceWorker.js ├── store.js ├── router.js └── App.vue ├── .env.development ├── .gitignore ├── .eslintrc.js ├── README.md └── package.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | } 5 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/img/bca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/bca.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /public/img/mandiri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/mandiri.png -------------------------------------------------------------------------------- /public/img/unavailable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/unavailable.png -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_NAME=Vueshop 2 | VUE_APP_BACKEND_URL=http://larashop-api.test 3 | VUE_APP_API_URL=http://larashop-api.test -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laravel-vue-book/vueshop/HEAD/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuetify from 'vuetify/lib'; 3 | 4 | Vue.use(Vuetify); 5 | 6 | export default new Vuetify({ 7 | icons: { 8 | iconfont: 'mdi', 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /~ 5 | package-lock.json* 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import './plugins/axios' 3 | import App from './App.vue' 4 | import router from './router' 5 | import store from './store' 6 | import './registerServiceWorker' 7 | import vuetify from './plugins/vuetify' 8 | import './plugins/helper' 9 | 10 | Vue.config.productionTip = false 11 | 12 | new Vue({ 13 | router, 14 | store, 15 | vuetify, 16 | render: h => h(App) 17 | }).$mount('#app') 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 13 | }, 14 | parserOptions: { 15 | parser: 'babel-eslint' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import { shallowMount } from '@vue/test-utils' 3 | import HelloWorld from '@/components/HelloWorld.vue' 4 | 5 | describe('HelloWorld.vue', () => { 6 | it('renders props.msg when passed', () => { 7 | const msg = 'new message' 8 | const wrapper = shallowMount(HelloWorld, { 9 | propsData: { msg } 10 | }) 11 | expect(wrapper.text()).to.include(msg) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /src/plugins/helper.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | import Vue from 'vue' 3 | const Helper = { 4 | install(Vue) { 5 | Vue.prototype.appName = process.env.VUE_APP_NAME 6 | Vue.prototype.getImage = function (image){ 7 | if(image!=null && image.length>0 && image!=undefined){ 8 | return process.env.VUE_APP_BACKEND_URL + "/images"+ image 9 | } 10 | return "/img/unavailable.png" 11 | } 12 | } 13 | } 14 | 15 | Vue.use(Helper) -------------------------------------------------------------------------------- /src/stores/auth.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | user : {}, 5 | }, 6 | mutations: { 7 | set: (state, payload) => { 8 | state.user = payload 9 | }, 10 | }, 11 | actions: { 12 | set: ({commit}, payload) => { 13 | commit('set', payload) 14 | }, 15 | }, 16 | getters: { 17 | user : state => state.user, 18 | guest : state => Object.keys(state.user).length === 0, 19 | } 20 | } -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vueshop", 3 | "short_name": "vueshop", 4 | "icons": [ 5 | { 6 | "src": "./img/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#000000", 19 | "theme_color": "#4DBA87" 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Artboard 46 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vueshop 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Run your tests 19 | ``` 20 | npm run test 21 | ``` 22 | 23 | ### Lints and fixes files 24 | ``` 25 | npm run lint 26 | ``` 27 | 28 | ### Run your unit tests 29 | ``` 30 | npm run test:unit 31 | ``` 32 | 33 | ### Customize configuration 34 | See [Configuration Reference](https://cli.vuejs.org/config/). 35 | -------------------------------------------------------------------------------- /src/stores/alert.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | status : false, 5 | color : 'success', // warning, error 6 | text : '' 7 | }, 8 | mutations: { 9 | set: (state, payload) => { 10 | state.status = payload.status 11 | state.text = payload.text 12 | state.color = payload.color 13 | }, 14 | }, 15 | actions: { 16 | set: ({commit}, payload) => { 17 | commit('set', payload) 18 | }, 19 | }, 20 | getters: { 21 | status : state => state.status, 22 | color : state => state.color, 23 | text : state => state.text 24 | } 25 | } -------------------------------------------------------------------------------- /src/stores/region.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | provinces: [], 5 | cities: [], 6 | }, 7 | mutations: { 8 | setProvinces: (state, value) => { 9 | state.provinces = value 10 | }, 11 | setCities: (state, value) => { 12 | state.cities = value 13 | }, 14 | }, 15 | actions: { 16 | setProvinces: ({commit}, value) => { 17 | commit('setProvinces', value) 18 | }, 19 | setCities: ({commit}, value) => { 20 | commit('setCities', value) 21 | }, 22 | }, 23 | getters: { 24 | provinces: state => state.provinces, 25 | cities: state => state.cities, 26 | } 27 | } -------------------------------------------------------------------------------- /src/views/Profile.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vueshop 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/BookItem.vue: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /src/stores/dialog.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | status : false, 5 | component : 'search', // search or login or other 6 | }, 7 | mutations: { 8 | setStatus: (state, status) => { 9 | state.status = status 10 | }, 11 | setComponent: (state, component) => { 12 | state.component = component 13 | }, 14 | }, 15 | actions: { 16 | setStatus: ({commit}, status) => { 17 | commit('setStatus', status) 18 | }, 19 | setComponent: ({commit}, component) => { 20 | commit('setComponent', component) 21 | commit('setStatus', true) 22 | }, 23 | }, 24 | getters: { 25 | status : state => state.status, 26 | component : state => state.component, 27 | } 28 | } -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/components/Alert.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import cart from '@/stores/cart' 4 | import alert from '@/stores/alert' 5 | import auth from '@/stores/auth' 6 | import dialog from '@/stores/dialog' 7 | import region from '@/stores/region' 8 | import VuexPersist from 'vuex-persist' 9 | 10 | const vuexPersist = new VuexPersist({ 11 | key: 'my-app', 12 | storage: localStorage 13 | }) 14 | 15 | Vue.use(Vuex) 16 | 17 | export default new Vuex.Store({ 18 | plugins: [vuexPersist.plugin], 19 | state: { 20 | prevUrl: '', 21 | payment: [] 22 | }, 23 | mutations: { 24 | setPrevUrl: (state, value) => { 25 | state.prevUrl = value 26 | }, 27 | setPayment: (state, value) => { 28 | state.payment = value 29 | }, 30 | }, 31 | actions: { 32 | setPrevUrl: ({commit}, value) => { 33 | commit('setPrevUrl', value) 34 | }, 35 | setPayment: ({commit}, value) => { 36 | commit('setPayment', value) 37 | }, 38 | }, 39 | getters: { 40 | prevUrl: state => state.prevUrl, 41 | payment: state => state.payment, 42 | }, 43 | modules: { 44 | cart, 45 | alert, 46 | auth, 47 | dialog, 48 | region 49 | } 50 | }) 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vueshop", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "test:unit": "vue-cli-service test:unit" 10 | }, 11 | "dependencies": { 12 | "core-js": "^2.6.5", 13 | "register-service-worker": "^1.6.2", 14 | "vue": "^2.6.10", 15 | "vue-router": "^3.0.3", 16 | "vuetify": "^2.0.0", 17 | "vuex": "^3.0.1", 18 | "vuex-persist": "^2.0.1" 19 | }, 20 | "devDependencies": { 21 | "@vue/cli-plugin-babel": "^3.9.0", 22 | "@vue/cli-plugin-eslint": "^3.9.0", 23 | "@vue/cli-plugin-pwa": "^3.9.0", 24 | "@vue/cli-plugin-unit-mocha": "^3.9.0", 25 | "@vue/cli-service": "^3.9.0", 26 | "@vue/test-utils": "1.0.0-beta.29", 27 | "axios": "^0.18.0", 28 | "babel-eslint": "^10.0.1", 29 | "chai": "^4.1.2", 30 | "eslint": "^5.16.0", 31 | "eslint-plugin-vue": "^5.0.0", 32 | "sass": "^1.17.4", 33 | "sass-loader": "^7.1.0", 34 | "stylus": "^0.54.5", 35 | "stylus-loader": "^3.0.2", 36 | "vue-cli-plugin-axios": "0.0.4", 37 | "vue-cli-plugin-vuetify": "^0.6.1", 38 | "vue-template-compiler": "^2.6.10", 39 | "vuetify-loader": "^1.2.2" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/views/Books.vue: -------------------------------------------------------------------------------- 1 | 26 | 59 | -------------------------------------------------------------------------------- /src/plugins/axios.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import Vue from 'vue'; 4 | import axios from "axios"; 5 | 6 | // Full config: https://github.com/axios/axios#request-config 7 | // axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || ''; 8 | // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; 9 | // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 10 | 11 | let config = { 12 | baseURL: process.env.VUE_APP_API_URL + '/v1', 13 | // baseURL: process.env.baseURL || process.env.apiUrl || "" 14 | // timeout: 60 * 1000, // Timeout 15 | // withCredentials: true, // Check cross-site Access-Control 16 | }; 17 | 18 | const _axios = axios.create(config); 19 | 20 | _axios.interceptors.request.use( 21 | function(config) { 22 | // Do something before request is sent 23 | return config; 24 | }, 25 | function(error) { 26 | // Do something with request error 27 | return Promise.reject(error); 28 | } 29 | ); 30 | 31 | // Add a response interceptor 32 | _axios.interceptors.response.use( 33 | function(response) { 34 | // Do something with response data 35 | return response; 36 | }, 37 | function(error) { 38 | // Do something with response error 39 | return Promise.reject(error); 40 | } 41 | ); 42 | 43 | Plugin.install = function(Vue) { 44 | Vue.axios = _axios; 45 | window.axios = _axios; 46 | Object.defineProperties(Vue.prototype, { 47 | axios: { 48 | get() { 49 | return _axios; 50 | } 51 | }, 52 | $axios: { 53 | get() { 54 | return _axios; 55 | } 56 | }, 57 | }); 58 | }; 59 | 60 | Vue.use(Plugin) 61 | 62 | export default Plugin; 63 | -------------------------------------------------------------------------------- /src/views/MyOrder.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /src/views/Categories.vue: -------------------------------------------------------------------------------- 1 | 36 | 66 | -------------------------------------------------------------------------------- /src/views/Category.vue: -------------------------------------------------------------------------------- 1 | 37 | 74 | -------------------------------------------------------------------------------- /src/views/Payment.vue: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 73 | -------------------------------------------------------------------------------- /src/components/Search.vue: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /src/stores/cart.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | carts : [], 5 | }, 6 | mutations: { 7 | insert: (state, payload) => { 8 | state.carts.push({ 9 | id: payload.id, 10 | title: payload.title, 11 | cover: payload.cover, 12 | price: payload.price, 13 | weight: payload.weight, 14 | quantity: 1 15 | }) 16 | }, 17 | update: (state, payload) => { 18 | let idx = state.carts.indexOf(payload); 19 | state.carts.splice(idx,1,{ 20 | id: payload.id, 21 | title: payload.title, 22 | cover: payload.cover, 23 | price: payload.price, 24 | weight: payload.weight, 25 | quantity: payload.quantity 26 | }); 27 | if(payload.quantity<=0){ 28 | state.carts.splice(idx,1) 29 | } 30 | }, 31 | set: (state, payload) => { 32 | state.carts = payload 33 | }, 34 | }, 35 | actions: { 36 | add: ({state, commit}, payload) => { 37 | let cartItem = state.carts.find(item => item.id === payload.id) 38 | if(!cartItem){ 39 | commit('insert', payload) 40 | } 41 | else{ 42 | cartItem.quantity++ 43 | commit('update', cartItem) 44 | } 45 | }, 46 | remove: ({state, commit}, payload) => { 47 | let cartItem = state.carts.find(item => item.id === payload.id) 48 | if(cartItem){ 49 | cartItem.quantity-- 50 | commit('update', cartItem) 51 | } 52 | }, 53 | set: ({commit}, payload) => { 54 | commit('set', payload) 55 | }, 56 | }, 57 | getters: { 58 | carts : state => state.carts, 59 | count : (state) => { 60 | return state.carts.length 61 | }, 62 | totalPrice: (state) => { 63 | let total = 0 64 | state.carts.forEach(function(cart) { 65 | total += cart.price * cart.quantity 66 | }) 67 | return total 68 | }, 69 | totalQuantity: (state) => { 70 | let total = 0 71 | state.carts.forEach(function(cart) { 72 | total += cart.quantity 73 | }) 74 | return total 75 | }, 76 | totalWeight: (state) => { 77 | let total = 0 78 | state.carts.forEach(function(cart) { 79 | total += cart.weight 80 | }) 81 | return total 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from './views/Home.vue' 4 | import store from './store' 5 | 6 | Vue.use(Router) 7 | 8 | //export default new Router({ 9 | const router = new Router({ 10 | mode: 'history', 11 | base: process.env.BASE_URL, 12 | routes: [ 13 | { 14 | path: '/', 15 | name: 'home', 16 | component: Home 17 | }, 18 | { 19 | path: '/about', 20 | name: 'about', 21 | // route level code-splitting 22 | // this generates a separate chunk (about.[hash].js) for this route 23 | // which is lazy-loaded when the route is visited. 24 | component: () => import(/* webpackChunkName: "about" */ './views/About.vue') 25 | }, 26 | { 27 | path: '/categories', 28 | name: 'categories', 29 | component: () => import( /* webpackChunkName: "categories" */ './views/Categories.vue') 30 | }, 31 | { 32 | path: '/books', 33 | name: 'books', 34 | component: () => import( /* webpackChunkName: "books" */ './views/Books.vue') 35 | }, 36 | { 37 | path: '/category/:slug', 38 | name: 'category', 39 | component: () => import( /* webpackChunkName: "category" */ './views/Category.vue') 40 | }, 41 | { 42 | path: '/book/:slug', 43 | name: 'book', 44 | component: () => import( /* webpackChunkName: "book" */ './views/Book.vue') 45 | }, 46 | { 47 | path: '/checkout', 48 | name: 'checkout', 49 | component: () => import( /* webpackChunkName: "checkout" */ './views/Checkout.vue'), 50 | meta: { auth: true } 51 | }, 52 | { 53 | path: '/payment', 54 | name: 'payment', 55 | component: () => import( /* webpackChunkName: "payment" */ './views/Payment.vue'), 56 | meta: { auth: true } 57 | }, 58 | { 59 | path: '/profile', 60 | name: 'profile', 61 | component: () => import( /* webpackChunkName: "profile" */ './views/Profile.vue'), 62 | meta: { auth: true } 63 | }, 64 | { 65 | path: '/my-order', 66 | name: 'my-order', 67 | component: () => import( /* webpackChunkName: "my-order" */ './views/MyOrder.vue'), 68 | meta: { auth: true } 69 | }, 70 | ] 71 | }) 72 | 73 | router.beforeEach((to, from, next) => { 74 | // jika routing ada meta auth-nya maka 75 | if (to.matched.some(record => record.meta.auth)) { 76 | // jika user adalah guest 77 | if(store.getters['auth/guest']){ 78 | // tampilkan pesan bahwa harus login dulu 79 | store.dispatch('alert/set', { 80 | status : true, 81 | text : 'Login first', 82 | color : 'error', 83 | }) 84 | store.dispatch('setPrevUrl', to.path) 85 | // tampilkan form login 86 | store.dispatch('dialog/setComponent', 'login') 87 | } 88 | else{ 89 | next() 90 | } 91 | } 92 | else{ 93 | next() 94 | } 95 | }) 96 | 97 | export default router; -------------------------------------------------------------------------------- /src/views/Book.vue: -------------------------------------------------------------------------------- 1 | 61 | 107 | -------------------------------------------------------------------------------- /src/components/Cart.vue: -------------------------------------------------------------------------------- 1 | 67 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 143 | -------------------------------------------------------------------------------- /src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /src/components/Register.vue: -------------------------------------------------------------------------------- 1 | 62 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 127 | -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/views/Checkout.vue: -------------------------------------------------------------------------------- 1 | 168 | --------------------------------------------------------------------------------