├── src
├── features
│ ├── login
│ │ ├── store.js
│ │ ├── service.js
│ │ └── main.vue
│ ├── account
│ │ ├── store.js
│ │ ├── service.js
│ │ ├── components
│ │ │ ├── address-edit.vue
│ │ │ └── countries.js
│ │ └── main.vue
│ ├── dashboard
│ │ ├── service.js
│ │ ├── test.css
│ │ ├── store.js
│ │ ├── components
│ │ │ ├── line-chart.vue
│ │ │ └── chart.vue
│ │ └── main.vue
│ ├── wip
│ │ └── main.vue
│ ├── tutorial
│ │ └── main.vue
│ ├── billing
│ │ └── main.vue
│ └── premium
│ │ └── main.vue
├── styles
│ ├── scss
│ │ ├── _vendor.scss
│ │ ├── _variables.scss
│ │ └── main.scss
│ └── stylus
│ │ ├── 2-tools
│ │ └── 2-tools.styl
│ │ ├── 7-utils
│ │ └── 7-utils.styl
│ │ ├── 3-generic
│ │ └── 3-generic.styl
│ │ ├── 5-objects
│ │ └── 5-objects.styl
│ │ ├── 4-elements
│ │ └── 4-elements.styl
│ │ ├── 6-components
│ │ ├── 6-components.styl
│ │ └── vendor.styl
│ │ ├── 1-settings
│ │ ├── vendor.styl
│ │ ├── 1-settings.styl
│ │ └── variables.styl
│ │ └── main.styl
├── assets
│ ├── logo.png
│ └── images
│ │ ├── logo.png
│ │ ├── backdrop.jpg
│ │ ├── profile.jpg
│ │ ├── traffic-cone.svg
│ │ ├── oops.svg
│ │ ├── logo-name.svg
│ │ └── logo.svg
├── http
│ ├── index.js
│ ├── router.js
│ └── routes.js
├── layouts
│ ├── public
│ │ └── main.vue
│ └── default
│ │ └── main.vue
├── store
│ ├── index.js
│ ├── plugins.js
│ └── common.js
├── constants
│ └── index.js
├── components
│ ├── app-footer.vue
│ ├── app-snackbar.vue
│ ├── app-dialog.vue
│ ├── Hello.vue
│ ├── app-bar.vue
│ ├── loading.vue
│ └── app-sidebar.vue
├── auth
│ ├── store.js
│ ├── index.js
│ └── helpers.js
├── app.vue
└── main.js
├── .eslintignore
├── config
├── prod.env.js
├── test.env.js
├── dev.env.js
└── index.js
├── static
├── images
│ └── mountains.png
├── img
│ └── icons
│ │ ├── favicon.ico
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── mstile-150x150.png
│ │ ├── apple-touch-icon.png
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── msapplication-icon-144x144.png
│ │ └── safari-pinned-tab.svg
└── manifest.json
├── .editorconfig
├── .postcssrc.js
├── .gitignore
├── .vscode
├── extensions.json
└── settings.json
├── .babelrc
├── test
└── e2e
│ ├── specs
│ └── test.js
│ ├── custom-assertions
│ └── elementCount.js
│ ├── runner.js
│ └── nightwatch.conf.js
├── .eslintrc.js
├── README.md
├── index.html
└── package.json
/src/features/login/store.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/scss/_vendor.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/features/account/store.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/features/dashboard/service.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/features/login/service.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/scss/_variables.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/stylus/2-tools/2-tools.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/stylus/7-utils/7-utils.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/stylus/3-generic/3-generic.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/stylus/5-objects/5-objects.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/stylus/4-elements/4-elements.styl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 |
--------------------------------------------------------------------------------
/src/styles/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import '_variables';
2 | @import '_vendor';
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/src/features/dashboard/test.css:
--------------------------------------------------------------------------------
1 | .test {
2 | background-color: red;
3 | }
--------------------------------------------------------------------------------
/src/styles/stylus/6-components/6-components.styl:
--------------------------------------------------------------------------------
1 | @import 'vendor.styl'
2 |
--------------------------------------------------------------------------------
/src/styles/stylus/1-settings/vendor.styl:
--------------------------------------------------------------------------------
1 | $color-pack = false // Let's save 30k
2 |
--------------------------------------------------------------------------------
/src/styles/stylus/1-settings/1-settings.styl:
--------------------------------------------------------------------------------
1 | @import 'vendor'
2 | @import 'variables'
3 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/src/assets/images/logo.png
--------------------------------------------------------------------------------
/static/images/mountains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/images/mountains.png
--------------------------------------------------------------------------------
/src/assets/images/backdrop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/src/assets/images/backdrop.jpg
--------------------------------------------------------------------------------
/src/assets/images/profile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/src/assets/images/profile.jpg
--------------------------------------------------------------------------------
/static/img/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/favicon.ico
--------------------------------------------------------------------------------
/static/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/static/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/static/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/src/styles/stylus/6-components/vendor.styl:
--------------------------------------------------------------------------------
1 | @import '~vuetify/src/stylus/main'
2 |
3 | .application.theme--light
4 | background: #FFFFFF
--------------------------------------------------------------------------------
/static/img/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/static/img/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/static/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/static/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prograhammer/vue-pizza/HEAD/static/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const merge = require('webpack-merge')
4 | const devEnv = require('./dev.env')
5 |
6 | module.exports = merge(devEnv, {
7 | NODE_ENV: '"testing"'
8 | })
9 |
--------------------------------------------------------------------------------
/src/styles/stylus/1-settings/variables.styl:
--------------------------------------------------------------------------------
1 | $app-primary = #21CE99
2 | $app-secondary = #D81B60
3 | $app-accent = #805441
4 | $app-success = #61B865
5 | $app-light-grey = #E1E2E1
6 | $app-error = #FF6666
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const merge = require('webpack-merge')
4 | const prodEnv = require('./prod.env')
5 |
6 | module.exports = merge(prodEnv, {
7 | NODE_ENV: '"development"'
8 | })
9 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserlist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/http/index.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import router from './router'
3 |
4 | export const http = {
5 | install (Vue, options) {
6 | Vue.prototype.$http = Vue.http = axios.create()
7 | }
8 | }
9 |
10 | export { router }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/e2e/reports
8 | selenium-debug.log
9 | package-lock.json
10 |
11 | # Editor directories and files
12 | .idea
13 | *.suo
14 | *.ntvs*
15 | *.njsproj
16 | *.sln
17 |
--------------------------------------------------------------------------------
/src/layouts/public/main.vue:
--------------------------------------------------------------------------------
1 |
2 | v-app
3 | transition(name="slide" mode="out-in")
4 | router-view
5 |
6 |
7 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import auth from '@/auth/store'
4 | import common from './common'
5 | import { localStoragePlugin } from './plugins'
6 |
7 | Vue.use(Vuex)
8 |
9 | export default new Vuex.Store({
10 | modules: { common, auth },
11 | plugins: [localStoragePlugin]
12 | })
13 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
6 | "dbaeumer.vscode-eslint",
7 | "sysoev.language-stylus",
8 | "octref.vetur"
9 | ]
10 | }
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": [ "istanbul" ]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/styles/stylus/main.styl:
--------------------------------------------------------------------------------
1 | // Follows ITCSS: https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
2 | // Note: You may need to add a /vendor folder to some of these folders for working
3 | // with vendor styles. Be careful to add them in the order you need.
4 | @import '1-settings'
5 | @import '2-tools'
6 | @import '3-generic'
7 | @import '4-elements'
8 | @import '5-objects'
9 | @import '6-components'
10 | @import '7-utils'
--------------------------------------------------------------------------------
/src/features/dashboard/store.js:
--------------------------------------------------------------------------------
1 | import store from '@/store'
2 |
3 | store.registerModule('dashboard', {
4 | namespaced: true,
5 |
6 | // State loaded when this component is first loaded.
7 | state: {
8 | test: 0
9 | },
10 |
11 | mutations: {
12 | updateTest (state, newVal) {
13 | state.test = newVal
14 | }
15 | },
16 |
17 | actions: {
18 | updateTest ({ state, commit, rootState, dispatch }, newVal) {
19 | console.log(newVal)
20 | commit('updateTest', newVal)
21 | }
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/src/constants/index.js:
--------------------------------------------------------------------------------
1 | // Testing
2 | export const DEBUG = true
3 |
4 | // Backend API endpoints
5 | export const API_BASE_URL = '/api'
6 | export const REFRESH_TOKEN_URL = '/auth'
7 |
8 | /**
9 | * Key for local storage.
10 | *
11 | * Set the key to use in local storage to hold persistant data. If logged in,
12 | * you can see this key by going to Chrome > dev tools > application tab,
13 | * then choosing "Local Storage" and "http://localhost:8080".
14 | *
15 | * @type {string}
16 | */
17 | export const STORAGE_KEY = 'vue-pizza'
18 |
--------------------------------------------------------------------------------
/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-pizza",
3 | "short_name": "Vue Pizza",
4 | "icons": [
5 | {
6 | "src": "/app/static/img/icons/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/app/static/img/icons/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "start_url": "/app/index.html",
17 | "display": "standalone",
18 | "background_color": "#000000",
19 | "theme_color": "#4DBA87"
20 | }
21 |
--------------------------------------------------------------------------------
/src/components/app-footer.vue:
--------------------------------------------------------------------------------
1 |
2 | v-footer.my-appfooter(:class="{ 'my-appfooter--sidebar-open': sidebarVisibility }")
3 | .grey--text © 2018 Your Company Here
4 |
5 |
6 |
17 |
18 |
26 |
--------------------------------------------------------------------------------
/src/features/dashboard/components/line-chart.vue:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js PWA')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/features/dashboard/components/chart.vue:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/src/features/wip/main.vue:
--------------------------------------------------------------------------------
1 |
2 | v-container.my-wip(fluid fill-height text-xs-center)
3 | v-layout(justify-center align-center)
4 | v-flex.my-wip__hero(text-xs-center)
5 | img.my-wip__cone(src='~/@/assets/images/traffic-cone.svg' alt='Work-in-progress')
6 | div
7 | |Work-in-progress
8 |
9 |
10 |
11 |
28 |
29 |
39 |
--------------------------------------------------------------------------------
/src/auth/store.js:
--------------------------------------------------------------------------------
1 | const defaults = {
2 | isLoggedIn: false,
3 | accessToken: null,
4 | refreshToken: null,
5 | user: {
6 | name: '',
7 | id: ''
8 | }
9 | }
10 |
11 | const auth = {
12 | namespaced: true,
13 |
14 | state: Object.assign({}, defaults),
15 |
16 | mutations: {
17 | update (state, data) {
18 | state = Object.assign({}, defaults, data)
19 | },
20 | clear (state) {
21 | state = Object.assign(state, defaults)
22 | }
23 | },
24 |
25 | actions: {
26 | clear ({ state, commit, rootState, dispatch }) {
27 | commit('clear')
28 | },
29 | update ({ state, commit, rootState }, data) {
30 | commit('update', data)
31 | }
32 | }
33 | }
34 |
35 | export default auth
36 |
--------------------------------------------------------------------------------
/src/store/plugins.js:
--------------------------------------------------------------------------------
1 | import auth from '@/auth/store'
2 | import * as constants from '@/constants'
3 |
4 | // Sync with local storage.
5 | if (localStorage.getItem(constants.STORAGE_KEY)) {
6 | const syncedState = JSON.parse(localStorage.getItem(constants.STORAGE_KEY))
7 | auth.state = Object.assign(auth.state, syncedState.auth)
8 | }
9 |
10 | // LocalStorage plugin.
11 | const localStoragePlugin = store => {
12 | store.subscribe((mutation, state) => {
13 | const syncedData = { auth: state.auth }
14 |
15 | localStorage.setItem(constants.STORAGE_KEY, JSON.stringify(syncedData))
16 |
17 | if (mutation.type === 'common/clear') {
18 | localStorage.removeItem(constants.STORAGE_KEY)
19 | }
20 | })
21 | }
22 |
23 | export { localStoragePlugin }
24 |
--------------------------------------------------------------------------------
/src/app.vue:
--------------------------------------------------------------------------------
1 |
2 | #app
3 | component(:is="component")
4 | slot
5 |
6 |
7 |
38 |
--------------------------------------------------------------------------------
/src/layouts/default/main.vue:
--------------------------------------------------------------------------------
1 |
2 | v-app.my-default-layout
3 | app-sidebar
4 | app-bar
5 | v-content(style="padding-top: 48px;")
6 | transition(name="slide" mode="out-in")
7 | router-view
8 | app-footer
9 | app-dialog
10 | app-snackbar
11 |
12 |
13 |
30 |
31 |
33 |
--------------------------------------------------------------------------------
/src/components/app-snackbar.vue:
--------------------------------------------------------------------------------
1 |
2 | .my-snackbar
3 | v-snackbar(
4 | :timeout='$store.state.common.snackbar.timeout'
5 | :color='$store.state.common.snackbar.color'
6 | v-model='snackbarActive')
7 | | {{ $store.state.common.snackbar.text }}
8 | v-btn(dark='' flat='' @click.native='snackbarActive = false') Close
9 |
10 |
11 |
32 |
33 |
36 |
--------------------------------------------------------------------------------
/src/components/app-dialog.vue:
--------------------------------------------------------------------------------
1 |
2 | .my-dialog
3 | v-dialog(v-model='dialogActive' max-width='500px')
4 | v-card
5 | v-card-title
6 | span {{ $store.state.common.dialog.text }}
7 | v-card-actions
8 | v-spacer
9 | v-btn(color='primary' flat='' @click.stop='dialogActive = false') Close
10 |
11 |
12 |
35 |
36 |
39 |
--------------------------------------------------------------------------------
/src/features/tutorial/main.vue:
--------------------------------------------------------------------------------
1 |
2 | v-container.my-tutorial(fluid fill-height text-xs-center)
3 | v-layout(justify-center align-center)
4 | v-flex.my-tutorial__hero(text-xs-center)
5 | div
6 | |Check out the tutorial on the project's Github Wiki.
7 | br
8 | br
9 | div
10 | v-btn(
11 | color="primay"
12 | href="https://github.com/prograhammer/vue-pizza/wiki"
13 | target="_blank"
14 | ) Go to Tutorial
15 |
16 |
17 |
18 |
35 |
36 |
46 |
--------------------------------------------------------------------------------
/src/assets/images/traffic-cone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // the name of the method is the filename.
3 | // can be used in tests like this:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // for how to write custom assertions see
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 | exports.assertion = function (selector, count) {
10 | this.message = 'Testing if element <' + selector + '> has count: ' + count
11 | this.expected = count
12 | this.pass = function (val) {
13 | return val === this.expected
14 | }
15 | this.value = function (res) {
16 | return res.value
17 | }
18 | this.command = function (cb) {
19 | var self = this
20 | return this.api.execute(function (selector) {
21 | return document.querySelectorAll(selector).length
22 | }, [selector], function (res) {
23 | cb.call(self, res)
24 | })
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // http://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint',
7 | sourceType: 'module'
8 | },
9 | env: {
10 | browser: true,
11 | jest: true
12 | },
13 | globals: {
14 | utils: true
15 | },
16 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
17 | // https://github.com/vuejs/eslint-plugin-vue
18 | extends: [
19 | 'standard',
20 | 'plugin:vue/recommended'
21 | ],
22 | // required to lint *.vue files
23 | plugins: [
24 | 'vue'
25 | ],
26 | // add your custom rules here
27 | 'rules': {
28 | // allow paren-less arrow functions
29 | 'arrow-parens': 0,
30 | // allow async-await
31 | 'generator-star-spacing': 0,
32 | // allow debugger during development
33 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :pizza: Vue Pizza
2 |
3 | > A tasty Vue.js starter project. Clone, remove `vue-pizza` everywhere, and add your own features. Also, read through the wiki.
4 |
5 | ## Demo
6 |
7 | [https://vue.pizza/app](https://vue.pizza/app)
8 |
9 | ## Why?
10 |
11 | A lot of starter projects or examples of Vue.js in the wild were:
12 |
13 | - Outdated.
14 | - No tutorial or wiki.
15 | - Involved unneccesary, complex, server-side-rendering/NUXT setups (this project is for authenticated, no SEO needed, static/cacheable apps that communicate to a backend server API).
16 | - Not comprehensive and didn't cover most of the elements necessary for real world apps.
17 | - This project was started from the latest official Vue-cli PWA template and built up from there.
18 |
19 | ## Wiki
20 |
21 | Visit the Github wiki tab [here](https://github.com/prograhammer/vue-pizza/wiki) to learn everything you need to know about
22 | how this starter project was built (which allows you to learn and rebuild this project from scratch if you want).
23 |
24 | ## Installation
25 |
26 | Very simple. See the Installation section in [wiki](https://github.com/prograhammer/vue-pizza/wiki).
27 |
28 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 | var server = require('../../build/dev-server.js')
4 |
5 | server.ready.then(() => {
6 | // 2. run the nightwatch test suite against it
7 | // to run in additional browsers:
8 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
9 | // 2. add it to the --env flag below
10 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
11 | // For more information on Nightwatch's config file, see
12 | // http://nightwatchjs.org/guide#settings-file
13 | var opts = process.argv.slice(2)
14 | if (opts.indexOf('--config') === -1) {
15 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
16 | }
17 | if (opts.indexOf('--env') === -1) {
18 | opts = opts.concat(['--env', 'chrome'])
19 | }
20 |
21 | var spawn = require('cross-spawn')
22 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
23 |
24 | runner.on('exit', function (code) {
25 | server.close()
26 | process.exit(code)
27 | })
28 |
29 | runner.on('error', function (err) {
30 | server.close()
31 | throw err
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import store from './store'
3 | import { sync } from 'vuex-router-sync'
4 | import { http, router } from './http'
5 | import auth from './auth'
6 | import Vuetify from 'vuetify'
7 | import URLSearchParams from 'url-search-params'
8 | import App from './app'
9 | import Loading from './components/loading'
10 | import Appbar from './components/app-bar'
11 | import Appfooter from './components/app-footer'
12 |
13 | Vue.config.productionTip = false
14 |
15 | // Polyfills
16 | global.URLSearchParams = URLSearchParams
17 |
18 | // Sync router to store, as `store.state.route`.
19 | sync(store, router)
20 |
21 | // Http and Auth plugins
22 | Vue.use(http)
23 | Vue.use(auth)
24 |
25 | // Vuetify
26 | Vue.use(Vuetify, {
27 | theme: {
28 | primary: '#21CE99',
29 | secondary: '#D81B60',
30 | accent: '#805441'
31 | }
32 | })
33 |
34 | // Styles
35 | require('./styles/scss/main.scss')
36 | require('./styles/stylus/main.styl')
37 |
38 | // Global Components
39 | Vue.component('loading', Loading)
40 | Vue.component('Appbar', Appbar)
41 | Vue.component('Appfooter', Appfooter)
42 |
43 | /* eslint-disable no-new */
44 | new Vue({
45 | el: '#app',
46 | router,
47 | store,
48 | render: h => h(App)
49 | })
50 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to override the default and user settings
2 | {
3 | // Settings for .js, .vue, .styl files.
4 | "[javascript]": {
5 | "editor.tabSize": 2,
6 | "editor.insertSpaces": true
7 | },
8 | "[vue]": {
9 | "editor.tabSize": 2,
10 | "editor.insertSpaces": true
11 | },
12 | "[stylus]": {
13 | "editor.tabSize": 2,
14 | "editor.insertSpaces": true
15 | },
16 |
17 | // This is required for ESLint to work in Vue in VS Code.
18 | "eslint.options": {
19 | "extensions": [".html", ".js", ".vue", ".jsx"]
20 | },
21 | "eslint.validate": [
22 | {
23 | "language": "html",
24 | "autoFix": true
25 | },
26 | {
27 | "language": "vue",
28 | "autoFix": true
29 | },
30 | {
31 | "language": "javascript",
32 | "autoFix": true
33 | },
34 | {
35 | "language": "javascriptreact",
36 | "autoFix": true
37 | }
38 | ],
39 |
40 | // When you hit ctrl+e to search, you don't want node_modules to be included.
41 | "search.exclude": {
42 | "**/.git": true,
43 | "**/node_modules": true,
44 | "**/tmp": true
45 | }
46 | }
--------------------------------------------------------------------------------
/src/features/account/service.js:
--------------------------------------------------------------------------------
1 | import store from '@/store'
2 | // import auth from '@/auth/helpers'
3 |
4 | export default class Service {
5 | constructor (options) {
6 | this.id = store.state.auth.user.id
7 | }
8 |
9 | getProfile () {
10 | // Mock data.
11 | // Replace this with actual call to backend server below.
12 | const parsed = {
13 | email: 'prograhammer@gmail.com',
14 | name: 'David Graham',
15 | country: 'USA',
16 | addressLine1: '1234 Some St.',
17 | addressLine2: '',
18 | state: 'Texas',
19 | zipcode: '78789'
20 | }
21 |
22 | // Simulate loading time.
23 | return new Promise((resolve) => {
24 | setTimeout(() => { resolve(parsed) }, 500)
25 | })
26 |
27 | /*
28 | return auth.get('/account')
29 | .then((response) => {
30 | const parsed = {
31 | email: response.email,
32 | name: response.name,
33 | country: response.country,
34 | addressLine1: response.address_line1,
35 | addressLine2: response.address_line2,
36 | state: response.state,
37 | zipcode: response.zipcode
38 | }
39 |
40 | return new Promise((resolve) => { resolve(parsed) })
41 | })
42 | .catch((error) => {
43 | return new Promise((resolve, reject) => { reject(error) })
44 | })
45 | */
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/features/billing/main.vue:
--------------------------------------------------------------------------------
1 |
2 | .my-billing
3 |
4 | Appbar
5 |
6 | v-tabs.elevation-0(dark v-model="currentTab" color="primary")
7 | // @TODO: Paths don't matter here, only route names. Make issue to Vuetify.
8 | v-tab(v-bind:to="{ name: 'account', path: '/account' }" ripple) Profile
9 | v-tab(v-bind:to="{ name: 'billing', path: '/billing' }" ripple) Billing
10 | v-tab(v-bind:to="{ name: 'market-link', path: '/market-link' }" ripple) Market Link
11 | v-tab(v-bind:to="{ name: 'prem-pts', path: '/prem-pts' }" ripple) Premium Points
12 |
13 | .my-billing__hero
14 | img.my-billing__cone(src='~/@/assets/images/traffic-cone.svg' alt='Under Construction')
15 | div
16 | |work-in-progress
17 |
18 |
19 |
20 |
40 |
41 |
56 |
--------------------------------------------------------------------------------
/src/features/premium/main.vue:
--------------------------------------------------------------------------------
1 |
2 | .my-prem-pts
3 |
4 | Appbar
5 |
6 | v-tabs.elevation-0(dark v-model="currentTab" color="primary")
7 | // @TODO: Paths don't matter here, only route names. Make issue to Vuetify.
8 | v-tab(v-bind:to="{ name: 'account', path: '/account' }" ripple) Profile
9 | v-tab(v-bind:to="{ name: 'billing', path: '/billing' }" ripple) Billing
10 | v-tab(v-bind:to="{ name: 'market-link', path: '/market-link' }" ripple) Market Link
11 | v-tab(v-bind:to="{ name: 'prem-pts', path: '/prem-pts' }" ripple) Premium Points
12 |
13 | .my-prem-pts__hero
14 | img.my-prem-pts__cone(src='~/@/assets/images/traffic-cone.svg' alt='Under Construction')
15 | div
16 | |work-in-progress
17 |
18 |
19 |
20 |
40 |
41 |
56 |
--------------------------------------------------------------------------------
/src/http/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import routes from './routes'
4 | import store from '@/store'
5 |
6 | Vue.use(Router)
7 |
8 | /**
9 | * Guard the route from unauthorized users.
10 | *
11 | * @param {Route} to The route we want to access.
12 | * @param {Route} from The route from which we are coming from.
13 | * @param {Function} next Callback for passing a route to be called next.
14 | * @return {void}
15 | */
16 | function guardRoute (to, from, next) {
17 | // work-around to get to the Vuex store (as of Vue 2.0)
18 | const auth = router.app.$options.store.state.auth
19 |
20 | if (!auth.isLoggedIn) {
21 | next({path: '/login', query: { redirect: to.fullPath }})
22 | } else {
23 | next()
24 | }
25 | }
26 |
27 | /**
28 | * The Router instance containing all the routes for the application.
29 | */
30 | const router = new Router({
31 | base: '/app',
32 | // mode: 'history', // <-- uncomment to turn on history mode (preferred)
33 | routes: routes.map(route => ({
34 | name: route.name,
35 | path: route.path,
36 | component: route.component,
37 | beforeEnter: (to, from, next) => {
38 | // Setup some per-page stuff.
39 | document.title = route.title
40 | store.dispatch('common/updateTitle', route.title)
41 | store.dispatch('common/updateLayout', route.layout)
42 |
43 | // Auth navigation guard.
44 | if (!route.isPublic) return guardRoute(to, from, next)
45 |
46 | next()
47 | }
48 | }))
49 | })
50 |
51 | export default router
52 |
--------------------------------------------------------------------------------
/src/components/Hello.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ msg }}
4 | Essential Links
5 |
6 |
12 | Ecosystem
13 |
14 |
19 |