├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── README.md ├── build ├── build.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── index.html ├── package.json ├── src ├── App.vue ├── assets │ ├── background.png │ ├── background.svg │ ├── fonts │ │ ├── Rubik-Black.ttf │ │ ├── Rubik-BlackItalic.ttf │ │ ├── Rubik-Bold.ttf │ │ ├── Rubik-BoldItalic.ttf │ │ ├── Rubik-Italic.ttf │ │ ├── Rubik-Light.ttf │ │ ├── Rubik-LightItalic.ttf │ │ ├── Rubik-Medium.ttf │ │ ├── Rubik-MediumItalic.ttf │ │ ├── Rubik-Regular.ttf │ │ ├── icomoon.eot │ │ ├── icomoon.svg │ │ ├── icomoon.ttf │ │ └── icomoon.woff │ ├── giphy.gif │ ├── grow.svg │ ├── grow2.svg │ ├── icons │ │ ├── Alert.svg │ │ ├── Baby.svg │ │ ├── Background.svg │ │ ├── Building House.svg │ │ ├── GeneralGoal.svg │ │ ├── GetLeft.svg │ │ ├── Grow.svg │ │ ├── Heart.svg │ │ ├── IconGrow.svg │ │ ├── IconGrowBlue.svg │ │ ├── List.svg │ │ ├── Loading.svg │ │ ├── School.svg │ │ ├── Tools.svg │ │ ├── Worldtrip.svg │ │ ├── img1.png │ │ ├── img2.png │ │ └── logotipo.svg │ ├── iphone.png │ ├── logo.png │ ├── styles │ │ ├── buttons.styl │ │ ├── mixins.styl │ │ ├── style.styl │ │ ├── typography.styl │ │ ├── variables.styl │ │ └── vendor │ │ │ ├── animate.styl │ │ │ └── vue2-animate │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ └── src │ │ │ ├── animations │ │ │ ├── bouncing │ │ │ │ ├── all.less │ │ │ │ ├── bounce.less │ │ │ │ ├── bounceDown.less │ │ │ │ ├── bounceLeft.less │ │ │ │ ├── bounceRight.less │ │ │ │ └── bounceUp.less │ │ │ ├── fading │ │ │ │ ├── all.less │ │ │ │ ├── fade.less │ │ │ │ ├── fadeDown.less │ │ │ │ ├── fadeDownBig.less │ │ │ │ ├── fadeLeft.less │ │ │ │ ├── fadeLeftBig.less │ │ │ │ ├── fadeRight.less │ │ │ │ ├── fadeRightBig.less │ │ │ │ ├── fadeUp.less │ │ │ │ └── fadeUpBig.less │ │ │ ├── rotating │ │ │ │ ├── all.less │ │ │ │ ├── rotate.less │ │ │ │ ├── rotateDownLeft.less │ │ │ │ ├── rotateDownRight.less │ │ │ │ ├── rotateUpLeft.less │ │ │ │ └── rotateUpRight.less │ │ │ ├── sliding │ │ │ │ ├── all.less │ │ │ │ ├── slideDown.less │ │ │ │ ├── slideLeft.less │ │ │ │ ├── slideRight.less │ │ │ │ └── slideUp.less │ │ │ └── zooming │ │ │ │ ├── all.less │ │ │ │ ├── zoom.less │ │ │ │ ├── zoomDown.less │ │ │ │ ├── zoomLeft.less │ │ │ │ ├── zoomRight.less │ │ │ │ └── zoomUp.less │ │ │ ├── make-transitions.less │ │ │ └── vue2-animate.less │ └── telasapp.png ├── common │ ├── directives │ │ └── masks.js │ ├── filters │ │ └── goals.js │ └── functions │ │ └── fun.js ├── main.js ├── router-config.js ├── shared-components │ ├── ActionBar.vue │ ├── Chart.vue │ ├── GeneralNotifications.vue │ ├── Hello.vue │ ├── Loading.vue │ ├── Navigation.vue │ ├── Range.vue │ └── Selector.vue ├── spa │ ├── Dash │ │ ├── Dash.vue │ │ ├── Item.vue │ │ └── RegisterModal.vue │ ├── Forbidden │ │ └── Forbidden.vue │ ├── Goal │ │ ├── Edit.vue │ │ ├── Goal.vue │ │ ├── NewGoal.vue │ │ ├── Notifications.vue │ │ └── SubGoalModal.vue │ ├── Home.vue │ ├── Landing │ │ └── Landing.vue │ ├── Login.vue │ └── Login │ │ └── Login.vue └── vuex │ ├── actions.js │ ├── database.js │ ├── getters.js │ ├── modules │ ├── goal.js │ ├── loader.js │ ├── notifications.js │ ├── subgoals.js │ └── user.js │ ├── mutation-types.js │ ├── resources.js │ └── store.js ├── static └── .gitkeep ├── test ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false 5 | } 6 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | parserOptions: { 5 | sourceType: 'module' 6 | }, 7 | extends: 'airbnb-base', 8 | // required to lint *.vue files 9 | plugins: [ 10 | 'html' 11 | ], 12 | // check if imports actually resolve 13 | 'settings': { 14 | 'import/resolver': { 15 | 'webpack': { 16 | 'config': 'build/webpack.base.conf.js' 17 | } 18 | } 19 | }, 20 | // add your custom rules here 21 | 'rules': { 22 | // don't require .vue extension when importing 23 | 'import/extensions': ['error', 'always', { 24 | 'js': 'never', 25 | 'vue': 'never' 26 | }], 27 | 'one-var': 0, 28 | 'no-param-reassign': 0, 29 | 'import/prefer-default-export': 0, 30 | // allow debugger during development 31 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | test/unit/coverage 6 | test/e2e/reports 7 | selenium-debug.log 8 | yarn.lock 9 | yarn-error.log 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Goal 2 | 3 | > We created a nice web application using yarn, webpack, vue.js, stylus and ECMAScript 6 to help its users reach their goals in life. 4 | > You can create goals and sub goals to better help you plan how to get it. 5 | 6 | ## Meet the team! 7 | 8 | * UX Designer: Garcia, Fernando [github](https://github.com/garciafsouza) [linkedin](https://www.linkedin.com/in/garciafsouza) 9 | * Frontend Developer: Silva, Pablo Henrique [github](https://github.com/pablohpsilva) [linkedin](https://www.linkedin.com/in/pablohpsilva) 10 | * Frontend Developer: Vilaboim, Lucas [github](https://github.com/vilaboim) [linkedin](https://www.linkedin.com/in/vilaboim) 11 | * Frontend Developer: Costa, Eduardo [github](https://github.com/eduardogc) [linkedin](https://www.linkedin.com/in/geceduardo) 12 | 13 | ## How to build it? 14 | 15 | ![The Magic Trick Team](src/assets/giphy.gif) 16 | 17 | ``` bash 18 | # install dependencies 19 | yarn install 20 | 21 | # serve with hot reload at localhost:8080 22 | yarn run dev 23 | 24 | # build for production with minification 25 | yarn run build 26 | 27 | # run unit tests 28 | yarn run unit 29 | 30 | # run e2e tests 31 | yarn run e2e 32 | 33 | # run all tests 34 | yarn test 35 | ``` 36 | ### vue-cli extra 37 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 38 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('shelljs/global') 3 | env.NODE_ENV = 'production' 4 | 5 | var path = require('path') 6 | var config = require('../config') 7 | var ora = require('ora') 8 | var webpack = require('webpack') 9 | var webpackConfig = require('./webpack.prod.conf') 10 | 11 | console.log( 12 | ' Tip:\n' + 13 | ' Built files are meant to be served over an HTTP server.\n' + 14 | ' Opening index.html over file:// won\'t work.\n' 15 | ) 16 | 17 | var spinner = ora('building for production...') 18 | spinner.start() 19 | 20 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 21 | 22 | rm('-rf', assetsPath) 23 | mkdir('-p', assetsPath) 24 | cp('-R', 'static/*', assetsPath) 25 | 26 | webpack(webpackConfig, function (err, stats) { 27 | spinner.stop() 28 | if (err) throw err 29 | process.stdout.write(stats.toString({ 30 | colors: true, 31 | modules: false, 32 | children: false, 33 | chunks: false, 34 | chunkModules: false 35 | }) + '\n') 36 | }) 37 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | if (!process.env.NODE_ENV) process.env.NODE_ENV = config.dev.env 3 | var path = require('path') 4 | var express = require('express') 5 | var webpack = require('webpack') 6 | var opn = require('opn') 7 | var proxyMiddleware = require('http-proxy-middleware') 8 | var webpackConfig = process.env.NODE_ENV === 'testing' 9 | ? require('./webpack.prod.conf') 10 | : require('./webpack.dev.conf') 11 | 12 | // default port where dev server listens for incoming traffic 13 | var port = process.env.PORT || config.dev.port 14 | // Define HTTP proxies to your custom API backend 15 | // https://github.com/chimurai/http-proxy-middleware 16 | var proxyTable = config.dev.proxyTable 17 | 18 | var app = express() 19 | var compiler = webpack(webpackConfig) 20 | 21 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 22 | publicPath: webpackConfig.output.publicPath, 23 | stats: { 24 | colors: true, 25 | chunks: false 26 | } 27 | }) 28 | 29 | var hotMiddleware = require('webpack-hot-middleware')(compiler) 30 | // force page reload when html-webpack-plugin template changes 31 | compiler.plugin('compilation', function (compilation) { 32 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 33 | hotMiddleware.publish({ action: 'reload' }) 34 | cb() 35 | }) 36 | }) 37 | 38 | // proxy api requests 39 | Object.keys(proxyTable).forEach(function (context) { 40 | var options = proxyTable[context] 41 | if (typeof options === 'string') { 42 | options = { target: options } 43 | } 44 | app.use(proxyMiddleware(context, options)) 45 | }) 46 | 47 | // handle fallback for HTML5 history API 48 | app.use(require('connect-history-api-fallback')()) 49 | 50 | // serve webpack bundle output 51 | app.use(devMiddleware) 52 | 53 | // enable hot-reload and state-preserving 54 | // compilation error display 55 | app.use(hotMiddleware) 56 | 57 | // serve pure static assets 58 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 59 | app.use(staticPath, express.static('./static')) 60 | 61 | module.exports = app.listen(port, function (err) { 62 | if (err) { 63 | console.log(err) 64 | return 65 | } 66 | var uri = 'http://localhost:' + port 67 | console.log('Listening at ' + uri + '\n') 68 | opn(uri) 69 | }) 70 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | // Extract CSS when that option is specified 29 | // (which is the case during production build) 30 | if (options.extract) { 31 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 32 | } else { 33 | return ['vue-style-loader', sourceLoader].join('!') 34 | } 35 | } 36 | 37 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 38 | return { 39 | css: generateLoaders(['css']), 40 | postcss: generateLoaders(['css']), 41 | less: generateLoaders(['css', 'less']), 42 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 43 | scss: generateLoaders(['css', 'sass']), 44 | stylus: generateLoaders(['css', 'stylus']), 45 | styl: generateLoaders(['css', 'stylus']) 46 | } 47 | } 48 | 49 | // Generate loaders for standalone style files (outside of .vue) 50 | exports.styleLoaders = function (options) { 51 | var output = [] 52 | var loaders = exports.cssLoaders(options) 53 | for (var extension in loaders) { 54 | var loader = loaders[extension] 55 | output.push({ 56 | test: new RegExp('\\.' + extension + '$'), 57 | loader: loader 58 | }) 59 | } 60 | return output 61 | } 62 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var projectRoot = path.resolve(__dirname, '../') 5 | 6 | var env = process.env.NODE_ENV 7 | // check env & config/index.js to decide weither to enable CSS Sourcemaps for the 8 | // various preprocessor loaders added to vue-loader at the end of this file 9 | var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap) 10 | var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap) 11 | var useCssSourceMap = cssSourceMapDev || cssSourceMapProd 12 | 13 | module.exports = { 14 | entry: { 15 | app: './src/main.js' 16 | }, 17 | output: { 18 | path: config.build.assetsRoot, 19 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 20 | filename: '[name].js' 21 | }, 22 | resolve: { 23 | extensions: ['', '.js', '.vue'], 24 | fallback: [path.join(__dirname, '../node_modules')], 25 | alias: { 26 | 'src': path.resolve(__dirname, '../src'), 27 | 'assets': path.resolve(__dirname, '../src/assets'), 28 | 'components': path.resolve(__dirname, '../src/components') 29 | } 30 | }, 31 | resolveLoader: { 32 | fallback: [path.join(__dirname, '../node_modules')] 33 | }, 34 | module: { 35 | preLoaders: [ 36 | { 37 | test: /\.vue$/, 38 | loader: 'eslint', 39 | include: projectRoot, 40 | exclude: /node_modules/ 41 | }, 42 | { 43 | test: /\.js$/, 44 | loader: 'eslint', 45 | include: projectRoot, 46 | exclude: /node_modules/ 47 | } 48 | ], 49 | loaders: [ 50 | { 51 | test: /\.vue$/, 52 | loader: 'vue' 53 | }, 54 | { 55 | test: /\.js$/, 56 | loader: 'babel', 57 | include: projectRoot, 58 | exclude: /node_modules/ 59 | }, 60 | { 61 | test: /\.json$/, 62 | loader: 'json' 63 | }, 64 | { 65 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 66 | loader: 'url', 67 | query: { 68 | limit: 10000, 69 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 70 | } 71 | }, 72 | { 73 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 74 | loader: 'url', 75 | query: { 76 | limit: 10000, 77 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 78 | } 79 | } 80 | ] 81 | }, 82 | eslint: { 83 | formatter: require('eslint-friendly-formatter') 84 | }, 85 | vue: { 86 | loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), 87 | postcss: [ 88 | require('autoprefixer')({ 89 | browsers: ['last 2 versions'] 90 | }) 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | 8 | // add hot-reload related code to entry chunks 9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 11 | }) 12 | 13 | module.exports = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 16 | }, 17 | // eval-source-map is faster for development 18 | devtool: '#eval-source-map', 19 | plugins: [ 20 | new webpack.DefinePlugin({ 21 | 'process.env': config.dev.env 22 | }), 23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 24 | new webpack.optimize.OccurenceOrderPlugin(), 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }) 33 | ] 34 | }) 35 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 16 | }, 17 | devtool: config.build.productionSourceMap ? '#source-map' : false, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 21 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 22 | }, 23 | vue: { 24 | loaders: utils.cssLoaders({ 25 | sourceMap: config.build.productionSourceMap, 26 | extract: true 27 | }) 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.optimize.OccurenceOrderPlugin(), 40 | // extract css into its own file 41 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 42 | // generate dist index.html with correct asset hash for caching. 43 | // you can customize output by editing /index.html 44 | // see https://github.com/ampedandwired/html-webpack-plugin 45 | new HtmlWebpackPlugin({ 46 | filename: process.env.NODE_ENV === 'testing' 47 | ? 'index.html' 48 | : config.build.index, 49 | template: 'index.html', 50 | inject: true, 51 | minify: { 52 | removeComments: true, 53 | collapseWhitespace: true, 54 | removeAttributeQuotes: true 55 | // more options: 56 | // https://github.com/kangax/html-minifier#options-quick-reference 57 | }, 58 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 59 | chunksSortMode: 'dependency' 60 | }), 61 | // split vendor js into its own file 62 | new webpack.optimize.CommonsChunkPlugin({ 63 | name: 'vendor', 64 | minChunks: function (module, count) { 65 | // any required modules inside node_modules are extracted to vendor 66 | return ( 67 | module.resource && 68 | /\.js$/.test(module.resource) && 69 | module.resource.indexOf( 70 | path.join(__dirname, '../node_modules') 71 | ) === 0 72 | ) 73 | } 74 | }), 75 | // extract webpack runtime and module manifest to its own file in order to 76 | // prevent vendor hash from being updated whenever app bundle is updated 77 | new webpack.optimize.CommonsChunkPlugin({ 78 | name: 'manifest', 79 | chunks: ['vendor'] 80 | }) 81 | ] 82 | }) 83 | 84 | if (config.build.productionGzip) { 85 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 86 | 87 | webpackConfig.plugins.push( 88 | new CompressionWebpackPlugin({ 89 | asset: '[path].gz[query]', 90 | algorithm: 'gzip', 91 | test: new RegExp( 92 | '\\.(' + 93 | config.build.productionGzipExtensions.join('|') + 94 | ')$' 95 | ), 96 | threshold: 10240, 97 | minRatio: 0.8 98 | }) 99 | ) 100 | } 101 | 102 | module.exports = webpackConfig 103 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: {}, 25 | // CSS Sourcemaps off by default because relative paths are "buggy" 26 | // with this option, according to the CSS-Loader README 27 | // (https://github.com/webpack/css-loader#sourcemaps) 28 | // In our experience, they generally work as expected, 29 | // just be aware of this issue when enabling this option. 30 | cssSourceMap: false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Goal by Grow 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "budgetingtool", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "pablohenrique ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "unit": "karma start test/unit/karma.conf.js --single-run", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" 14 | }, 15 | "dependencies": { 16 | "chart.js": "^2.3.0", 17 | "cleave.js": "^0.7.11", 18 | "pouchdb": "^6.0.7", 19 | "vue": "^2.0.1", 20 | "vue-resource": "^1.0.3", 21 | "vue-router": "^2.0.1", 22 | "vuex": "^2.0.0", 23 | "vuex-router-sync": "next" 24 | }, 25 | "devDependencies": { 26 | "autoprefixer": "^6.4.0", 27 | "babel-core": "^6.0.0", 28 | "babel-eslint": "^7.0.0", 29 | "babel-loader": "^6.0.0", 30 | "babel-plugin-transform-runtime": "^6.0.0", 31 | "babel-preset-es2015": "^6.0.0", 32 | "babel-preset-stage-2": "^6.0.0", 33 | "babel-register": "^6.0.0", 34 | "chai": "^3.5.0", 35 | "chromedriver": "^2.21.2", 36 | "connect-history-api-fallback": "^1.1.0", 37 | "cross-spawn": "^4.0.2", 38 | "css-loader": "^0.25.0", 39 | "eslint": "^3.7.1", 40 | "eslint-config-airbnb-base": "^8.0.0", 41 | "eslint-friendly-formatter": "^2.0.5", 42 | "eslint-import-resolver-webpack": "^0.6.0", 43 | "eslint-loader": "^1.5.0", 44 | "eslint-plugin-html": "^1.3.0", 45 | "eslint-plugin-import": "^1.16.0", 46 | "eventsource-polyfill": "^0.9.6", 47 | "express": "^4.13.3", 48 | "extract-text-webpack-plugin": "^1.0.1", 49 | "fastclick": "^1.0.6", 50 | "file-loader": "^0.9.0", 51 | "function-bind": "^1.0.2", 52 | "html-webpack-plugin": "^2.8.1", 53 | "http-proxy-middleware": "^0.17.2", 54 | "inject-loader": "^2.0.1", 55 | "isparta-loader": "^2.0.0", 56 | "json-loader": "^0.5.4", 57 | "karma": "^1.3.0", 58 | "karma-coverage": "^1.1.1", 59 | "karma-mocha": "^1.2.0", 60 | "karma-phantomjs-launcher": "^1.0.0", 61 | "karma-sinon-chai": "^1.2.0", 62 | "karma-sourcemap-loader": "^0.3.7", 63 | "karma-spec-reporter": "0.0.26", 64 | "karma-webpack": "^1.7.0", 65 | "less": "^2.7.1", 66 | "less-loader": "^2.2.3", 67 | "lodash": "^4.16.4", 68 | "lolex": "^1.4.0", 69 | "mocha": "^3.1.0", 70 | "moment": "^2.15.1", 71 | "nightwatch": "^0.9.8", 72 | "opn": "^4.0.2", 73 | "ora": "^0.3.0", 74 | "phantomjs-prebuilt": "^2.1.3", 75 | "selenium-server": "2.53.1", 76 | "shelljs": "^0.7.4", 77 | "sinon": "^1.17.3", 78 | "sinon-chai": "^2.8.0", 79 | "stylus": "^0.54.5", 80 | "stylus-loader": "^2.3.1", 81 | "url-loader": "^0.5.7", 82 | "vee-validate": "^1.0.0-beta.8", 83 | "vue-loader": "^9.4.0", 84 | "vue-style-loader": "^1.0.0", 85 | "vue2-animate": "^1.0.4", 86 | "webpack": "^1.13.2", 87 | "webpack-dev-middleware": "^1.8.3", 88 | "webpack-hot-middleware": "^2.12.2", 89 | "webpack-merge": "^0.14.1" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 36 | 37 | 40 | 74 | -------------------------------------------------------------------------------- /src/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/background.png -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Black.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-BlackItalic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Bold.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-BoldItalic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Italic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Light.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-LightItalic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Medium.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-MediumItalic.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Rubik-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/Rubik-Regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/icomoon.eot -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/icomoon.ttf -------------------------------------------------------------------------------- /src/assets/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/fonts/icomoon.woff -------------------------------------------------------------------------------- /src/assets/giphy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/giphy.gif -------------------------------------------------------------------------------- /src/assets/grow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 11 | 13 | 21 | 22 | 33 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/assets/grow2.svg: -------------------------------------------------------------------------------- 1 | Grow logo 6 | -------------------------------------------------------------------------------- /src/assets/icons/Alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 13 | 16 | 19 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/assets/icons/Baby.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 31 | 32 | 34 | 37 | 39 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/assets/icons/Building House.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/icons/GeneralGoal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/assets/icons/GetLeft.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/assets/icons/Grow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | Grow logo 7 | 10 | 12 | 14 | 33 | 34 | -------------------------------------------------------------------------------- /src/assets/icons/Heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 44 | 87 | 88 | -------------------------------------------------------------------------------- /src/assets/icons/IconGrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/assets/icons/IconGrowBlue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | Grow logo 7 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /src/assets/icons/List.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/Loading.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/School.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 31 | 32 | 34 | 37 | 39 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/assets/icons/Tools.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/icons/Worldtrip.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/icons/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/icons/img1.png -------------------------------------------------------------------------------- /src/assets/icons/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/icons/img2.png -------------------------------------------------------------------------------- /src/assets/icons/logotipo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 11 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/iphone.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/styles/buttons.styl: -------------------------------------------------------------------------------- 1 | @import "./variables" 2 | 3 | .Btn 4 | background transparent 5 | border-radius 3px 6 | box-shadow none 7 | cursor pointer 8 | font 300 13px $rubik 9 | outline none 10 | transition all ease .3s 11 | 12 | &:focus 13 | outline: none; 14 | 15 | .Btn__clean--white 16 | @extend .Btn 17 | border 2px solid #FFF 18 | color #FFF 19 | min-width 100px 20 | padding 10px 15px 21 | 22 | &:hover 23 | background $blue-color 24 | color #FFF 25 | 26 | .Btn__clean--blue 27 | @extend .Btn 28 | border 2px solid $blue-color 29 | color $blue-color 30 | min-width 100px 31 | padding 10px 15px 32 | 33 | &:hover 34 | background $blue-color 35 | color #FFF 36 | 37 | .Btn__clean--small 38 | @extend .Btn 39 | background none 40 | border 1px #FFF solid 41 | color #FFF 42 | font-size 14px 43 | font-weight 600 44 | height 40px 45 | margin-bottom 30px 46 | transition background-color .3s ease 47 | width 100% 48 | 49 | &:active 50 | background-color $primary-color 51 | transition background-color .3s ease 52 | -------------------------------------------------------------------------------- /src/assets/styles/mixins.styl: -------------------------------------------------------------------------------- 1 | /* ----- 2 | Forms 3 | ----- */ 4 | placeholder(element) 5 | {element}::-webkit-input-placeholder 6 | {block} 7 | 8 | {element}::-moz-placeholder 9 | {block} 10 | 11 | {element}:-ms-input-placeholder 12 | {block} 13 | 14 | /* ----- 15 | Flexbox 16 | ----- */ 17 | flex() 18 | display -ms-flexbox 19 | display -webkit-box 20 | display -webkit-flex 21 | display flex 22 | 23 | flex-direction(val) 24 | -webkit-flex-direction val 25 | -ms-flex-direction val 26 | flex-direction val 27 | 28 | flex-wrap(val) 29 | -webkit-flex-wrap val 30 | -ms-flex-wrap val 31 | flex-wrap val 32 | 33 | flex-justify(val) 34 | -webkit-justify-content val 35 | 36 | if val is 'flex-start' 37 | -ms-flex-line-pack start 38 | else if val is 'flex-end' 39 | -ms-flex-line-pack end 40 | else if val is 'space-between' 41 | -ms-flex-line-pack justify 42 | else if val is 'space-around' 43 | -ms-flex-line-pack distribute 44 | else 45 | -ms-flex-pack val 46 | 47 | justify-content val 48 | 49 | flex-align-items(val) 50 | -webkit-align-items val 51 | 52 | if val is 'flex-end' 53 | -ms-flex-align end 54 | if val is 'flex-start' 55 | -ms-flex-align start 56 | else 57 | -ms-flex-align val 58 | 59 | align-items val 60 | 61 | flex-align-self(val) 62 | -webkit-align-self val 63 | 64 | if val is 'flex-end' 65 | -ms-flex-item-align end 66 | if val is 'flex-start' 67 | -ms-flex-item-align start 68 | else 69 | -ms-flex-item-align val 70 | 71 | align-self val 72 | 73 | flex-align-content(val) 74 | -webkit-align-content flex-start 75 | 76 | if val is 'flex-start' 77 | -ms-flex-line-pack start 78 | else if val is 'flex-end' 79 | -ms-flex-line-pack end 80 | else if val is 'space-between' 81 | -ms-flex-line-pack justify 82 | else if val is 'space-around' 83 | -ms-flex-line-pack distribute 84 | else 85 | -ms-flex-line-pack val 86 | 87 | align-content flex-start 88 | 89 | flex-basis(val) 90 | -webkit-flex-basis val 91 | flex-basis val 92 | 93 | flex-order(val) 94 | -webkit-order val 95 | -ms-flex-order val 96 | order val 97 | 98 | /* ----- 99 | Element modifiers 100 | ----- */ 101 | square(val) 102 | width val 103 | height val 104 | 105 | text-overflow() 106 | overflow hidden 107 | white-space nowrap 108 | text-overflow ellipsis 109 | 110 | /** ----- 111 | Transform 112 | ----- */ 113 | transform() 114 | -webkit-transform arguments 115 | -moz-transform arguments 116 | transform arguments 117 | 118 | /** ----- 119 | Transitions 120 | ----- */ 121 | transition() 122 | -webkit-transition arguments 123 | transition arguments 124 | 125 | 126 | /** ----- 127 | Animation 128 | ----- */ 129 | keyframes(name) 130 | @-webkit-keyframes name 131 | {block} 132 | 133 | @keyframes name 134 | {block} 135 | 136 | /** ----- 137 | Range 138 | ----- */ 139 | rangeThumb() 140 | &::-webkit-slider-thumb 141 | {block} 142 | &::-moz-range-thumb 143 | {block} 144 | &::-ms-thumb 145 | {block} 146 | 147 | rangeTrack() 148 | &::-webkit-slider-runnable-track 149 | {block} 150 | &::-moz-range-track 151 | {block} 152 | &::-ms-track 153 | {block} 154 | -------------------------------------------------------------------------------- /src/assets/styles/style.styl: -------------------------------------------------------------------------------- 1 | @require "typography" 2 | @require "mixins" 3 | @require "buttons" 4 | 5 | @require "vendor/animate" 6 | 7 | body 8 | margin 0 9 | 10 | h1, 11 | h2, 12 | h3, 13 | h4, 14 | h5, 15 | h6 16 | margin 0 17 | 18 | p 19 | margin 0 20 | -------------------------------------------------------------------------------- /src/assets/styles/typography.styl: -------------------------------------------------------------------------------- 1 | @font-face 2 | font-family 'Rubik' 3 | font-style normal 4 | font-weight 300 5 | src: local('Rubik-Light'), url('assets/fonts/Rubik-Light.ttf') format('truetype') 6 | 7 | @font-face 8 | font-family 'Rubik' 9 | font-style italic 10 | font-weight 300 11 | src: local('Rubik-LightItalic'), url('assets/fonts/Rubik-LightItalic.ttf') format('truetype') 12 | 13 | @font-face 14 | font-family 'Rubik' 15 | font-style normal 16 | font-weight 400 17 | src: local('Rubik-Regular'), url('assets/fonts/Rubik-Regular.ttf') format('truetype') 18 | 19 | @font-face 20 | font-family 'Rubik' 21 | font-style italic 22 | font-weight 400 23 | src: local('Rubik-Italic'), url('assets/fonts/Rubik-Italic.ttf') format('truetype') 24 | 25 | @font-face 26 | font-family 'Rubik' 27 | font-style normal 28 | font-weight 600 29 | src: local('Rubik-Medium'), url('assets/fonts/Rubik-Medium.ttf') format('truetype') 30 | 31 | @font-face 32 | font-family 'Rubik' 33 | font-style italic 34 | font-weight 600 35 | src: local('Rubik-MediumItalic'), url('assets/fonts/Rubik-MediumItalic.ttf') format('truetype') 36 | 37 | @font-face { 38 | font-family: 'icomoon'; 39 | src: url('assets/fonts/icomoon.eot?uir1xc'); 40 | src: url('assets/fonts/icomoon.eot?uir1xc#iefix') format('embedded-opentype'), 41 | url('assets/fonts/icomoon.ttf?uir1xc') format('truetype'), 42 | url('assets/fonts/icomoon.woff?uir1xc') format('woff'), 43 | url('assets/fonts/icomoon.svg?uir1xc#icomoon') format('svg'); 44 | font-weight: normal; 45 | font-style: normal; 46 | } 47 | 48 | [class^="icon-"], [class*=" icon-"] { 49 | font-family: 'icomoon'; 50 | speak: none; 51 | font-style: normal; 52 | font-weight: normal; 53 | font-variant: normal; 54 | text-transform: none; 55 | line-height: 1; 56 | -webkit-font-smoothing: antialiased; 57 | -moz-osx-font-smoothing: grayscale; 58 | } 59 | 60 | .icon-alert:before { 61 | content: "\e900"; 62 | } 63 | 64 | .icon-house:before { 65 | content: "\e901"; 66 | } 67 | 68 | .icon-general-goal:before { 69 | content: "\e902"; 70 | } 71 | 72 | .icon-left:before { 73 | content: "\e903"; 74 | } 75 | 76 | .icon-list:before { 77 | content: "\e904"; 78 | } 79 | 80 | .icon-baby:before { 81 | content: "\e905"; 82 | } 83 | 84 | .icon-tool:before { 85 | content: "\e906"; 86 | } 87 | 88 | .icon-worldtrip:before { 89 | content: "\e907"; 90 | } 91 | 92 | .icon-cancel:before { 93 | content: "\e908"; 94 | } 95 | 96 | .icon-airplane:before { 97 | content: "\e909"; 98 | } 99 | 100 | .icon-car:before { 101 | content: "\e90a"; 102 | } 103 | 104 | .icon-down-arrow:before { 105 | content: "\e90b"; 106 | } 107 | -------------------------------------------------------------------------------- /src/assets/styles/variables.styl: -------------------------------------------------------------------------------- 1 | $rubik = "Rubik", Arial, sans-serif 2 | 3 | $primary-color = #40C5E7 4 | $sec-color = #6EF83E 5 | $trd-color = #B9B9B9 6 | $danger-color = #FF3636 7 | $green-color = #2CE46A 8 | $red-color = #E42D2C 9 | $blue-color = #40A2CB 10 | $yellow-color = #F3F035 11 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Hayden Bickerton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/README.md: -------------------------------------------------------------------------------- 1 | # vue2-animate for Vue.js 2.0 2 | 3 | *Cross-browser CSS3 animation library* 4 | 5 | [![Version](https://img.shields.io/npm/v/vue2-animate.svg?style=flat-square)](https://www.npmjs.com/package/vue2-animate) 6 | [![License](https://img.shields.io/npm/l/vue2-animate.svg?style=flat-square)](LICENSE) 7 | 8 | A [Vue.js](http://vuejs.org/ "Vue.js") port of [Animate.css](https://github.com/daneden/animate.css "Animate.css"). For use with Vue's built-in transitions. 9 | 10 | **This is modified version of: https://github.com/haydenbbickerton/vue-animate for Vue 2.0** 11 | 12 | ##Installation 13 | ####HTML 14 | Include the stylesheet: 15 | 16 | ```html 17 | 18 | 19 | 20 | ``` 21 | ####npm 22 | If you're on webpack and using the [css-loader](https://github.com/webpack/css-loader "css loader"), you can use something like this: 23 | ```shell 24 | npm install --save vue2-animate 25 | ``` 26 | ```js 27 | require('vue2-animate/dist/vue2-animate.min.css') 28 | ``` 29 | ####Less 30 | ```less 31 | @import "/src/vue2-animate.less"; 32 | ``` 33 | 34 | ####Building 35 | ```shell 36 | git clone https://github.com/asika32764/vue2-animate.git 37 | cd vue2-animate 38 | npm install 39 | npm run build #Compiled .css files go to the dist folder 40 | ``` 41 | 42 | ##Usage 43 | 44 | Use [Vue.js transitions](http://vuejs.org/guide/transitions.html "Vue.js Transitions") as you normally would, but for the transition name you will use one of [Animate.css animations](https://github.com/daneden/animate.css#basic-usage "animations") **removing** the ***In/Out*** from the name. 45 | 46 | For example, if I want to use *fadeInLeft* and *fadeOutLeft* on my element, I'll write: 47 | ```html 48 | 49 |
  • 50 | {{ item }} 51 |
  • 52 |
    53 | ``` 54 | enter/leave is already written in the stylesheet, so just remove *In/Out* from the name and you're golden. 55 | 56 | ####Custom Transition Classes 57 | 58 | Animate.css's original classnames are supported on enter/leave transitions. So if you're going to use [Custom Transition Classes](http://vuejs.org/guide/transitions.html#Custom-Transition-Classes "Custom Transition Classes"), you can either add *-enter/-leave* to the classes: 59 | 60 | ```html 61 | 66 |

    hello

    67 |
    68 | ``` 69 | Or use the regular *In/Out* syntax: 70 | 71 | ```html 72 | 77 |

    hello

    78 |
    79 | ``` 80 | 81 | ####Supported Animations 82 | Not all [Animate.css animations](https://github.com/daneden/animate.css#basic-usage "animations") are supported at the moment. Here is a list of what's in vue2-animate (aka - *what you can put in the transition="x"* attribute) as of right now: 83 | 84 | #####Bounce 85 | * `bounce` 86 | * `bounceDown` 87 | * `bounceLeft` 88 | * `bounceRight` 89 | * `bounceUp` 90 | 91 | #####Fade 92 | * `fade` 93 | * `fadeDown` 94 | * `fadeDownBig` 95 | * `fadeLeft` 96 | * `fadeLeftBig` 97 | * `fadeRight` 98 | * `fadeRightBig` 99 | * `fadeUp` 100 | * `fadeUpBig` 101 | 102 | #####Rotate 103 | * `rotate` 104 | * `rotateDownLeft` 105 | * `rotateDownRight` 106 | * `rotateUpLeft` 107 | * `rotateUpRight` 108 | 109 | #####Slide 110 | * `slideDown` 111 | * `slideLeft` 112 | * `slideRight` 113 | * `slideUp` 114 | 115 | #####Zoom 116 | * `zoom` 117 | * `zoomDown` 118 | * `zoomLeft` 119 | * `zoomRight` 120 | * `zoomUp` 121 | 122 | # License 123 | 124 | [MIT](http://opensource.org/licenses/MIT) 125 | 126 | ## Contributing 127 | 128 | Pull requests are welcome :) 129 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue2-animate", 3 | "version": "1.0.4", 4 | "description": "LESS cross-browser animation library, for use with Vue.js 2.0. Ported from Animate.css.", 5 | "author": { 6 | "name": "Simon Asika", 7 | "email": "asika32764@gmail.com" 8 | }, 9 | "homepage": "https://github.com/asika32764/vue2-animate", 10 | "license": "MIT", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/asika32764/vue2-animate.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/asika32764/vue2-animate/issues" 17 | }, 18 | "keywords": [ 19 | "less", 20 | "animate", 21 | "animate.css", 22 | "vue", 23 | "vue.js", 24 | "transition", 25 | "vue-animate", 26 | "css" 27 | ], 28 | "files": [ 29 | "dist/vue2-animate.css", 30 | "dist/vue2-animate.min.css", 31 | "src" 32 | ], 33 | "devDependencies": { 34 | "less": "^2.4.0", 35 | "less-plugin-autoprefix": "^1.5.1", 36 | "less-plugin-clean-css": "^1.5.0" 37 | }, 38 | "scripts": { 39 | "build": "lessc src/vue2-animate.less > dist/vue2-animate.css && lessc --clean-css='--compatibility=ie8 --advanced' src/vue2-animate.less > dist/vue2-animate.min.css", 40 | "less": "lessc src/vue2-animate.less > dist/vue2-animate.css", 41 | "minify": "lessc --clean-css='--compatibility=ie8 --advanced' src/vue2-animate.less > dist/vue2-animate.min.css" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/all.less: -------------------------------------------------------------------------------- 1 | @import 'bounce'; 2 | @import 'bounceDown'; 3 | @import 'bounceLeft'; 4 | @import 'bounceRight'; 5 | @import 'bounceUp'; 6 | 7 | @bounces: Down, Left, Right, Up; 8 | .make-transitions(bounce, @bounces); 9 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/bounce.less: -------------------------------------------------------------------------------- 1 | @keyframes bounceIn { 2 | from, 20%, 40%, 60%, 80%, to { 3 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 4 | } 5 | 6 | 0% { 7 | opacity: 0; 8 | transform: scale3d(.3, .3, .3); 9 | } 10 | 11 | 20% { 12 | transform: scale3d(1.1, 1.1, 1.1); 13 | } 14 | 15 | 40% { 16 | transform: scale3d(.9, .9, .9); 17 | } 18 | 19 | 60% { 20 | opacity: 1; 21 | transform: scale3d(1.03, 1.03, 1.03); 22 | } 23 | 24 | 80% { 25 | transform: scale3d(.97, .97, .97); 26 | } 27 | 28 | to { 29 | opacity: 1; 30 | transform: scale3d(1, 1, 1); 31 | } 32 | } 33 | 34 | @keyframes bounceOut { 35 | 20% { 36 | transform: scale3d(.9, .9, .9); 37 | } 38 | 39 | 50%, 55% { 40 | opacity: 1; 41 | transform: scale3d(1.1, 1.1, 1.1); 42 | } 43 | 44 | to { 45 | opacity: 0; 46 | transform: scale3d(.3, .3, .3); 47 | } 48 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/bounceDown.less: -------------------------------------------------------------------------------- 1 | @keyframes bounceInDown { 2 | from, 60%, 75%, 90%, to { 3 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 4 | } 5 | 6 | 0% { 7 | opacity: 0; 8 | transform: translate3d(0, -3000px, 0); 9 | } 10 | 11 | 60% { 12 | opacity: 1; 13 | transform: translate3d(0, 25px, 0); 14 | } 15 | 16 | 75% { 17 | transform: translate3d(0, -10px, 0); 18 | } 19 | 20 | 90% { 21 | transform: translate3d(0, 5px, 0); 22 | } 23 | 24 | to { 25 | transform: none; 26 | } 27 | } 28 | 29 | @keyframes bounceOutDown { 30 | 20% { 31 | transform: translate3d(0, 10px, 0); 32 | } 33 | 34 | 40%, 45% { 35 | opacity: 1; 36 | transform: translate3d(0, -20px, 0); 37 | } 38 | 39 | to { 40 | opacity: 0; 41 | transform: translate3d(0, 2000px, 0); 42 | } 43 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/bounceLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes bounceInLeft { 2 | from, 60%, 75%, 90%, to { 3 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 4 | } 5 | 6 | 0% { 7 | opacity: 0; 8 | transform: translate3d(-3000px, 0, 0); 9 | } 10 | 11 | 60% { 12 | opacity: 1; 13 | transform: translate3d(25px, 0, 0); 14 | } 15 | 16 | 75% { 17 | transform: translate3d(-10px, 0, 0); 18 | } 19 | 20 | 90% { 21 | transform: translate3d(5px, 0, 0); 22 | } 23 | 24 | to { 25 | transform: none; 26 | } 27 | } 28 | 29 | @keyframes bounceOutLeft { 30 | 20% { 31 | opacity: 1; 32 | transform: translate3d(20px, 0, 0); 33 | } 34 | 35 | to { 36 | opacity: 0; 37 | transform: translate3d(-2000px, 0, 0); 38 | } 39 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/bounceRight.less: -------------------------------------------------------------------------------- 1 | @keyframes bounceInRight { 2 | from, 60%, 75%, 90%, to { 3 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 4 | } 5 | 6 | from { 7 | opacity: 0; 8 | transform: translate3d(3000px, 0, 0); 9 | } 10 | 11 | 60% { 12 | opacity: 1; 13 | transform: translate3d(-25px, 0, 0); 14 | } 15 | 16 | 75% { 17 | transform: translate3d(10px, 0, 0); 18 | } 19 | 20 | 90% { 21 | transform: translate3d(-5px, 0, 0); 22 | } 23 | 24 | to { 25 | transform: none; 26 | } 27 | } 28 | 29 | @keyframes bounceOutRight { 30 | 20% { 31 | opacity: 1; 32 | transform: translate3d(-20px, 0, 0); 33 | } 34 | 35 | to { 36 | opacity: 0; 37 | transform: translate3d(2000px, 0, 0); 38 | } 39 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/bouncing/bounceUp.less: -------------------------------------------------------------------------------- 1 | @keyframes bounceInUp { 2 | from, 60%, 75%, 90%, to { 3 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); 4 | } 5 | 6 | from { 7 | opacity: 0; 8 | transform: translate3d(0, 3000px, 0); 9 | } 10 | 11 | 60% { 12 | opacity: 1; 13 | transform: translate3d(0, -20px, 0); 14 | } 15 | 16 | 75% { 17 | transform: translate3d(0, 10px, 0); 18 | } 19 | 20 | 90% { 21 | transform: translate3d(0, -5px, 0); 22 | } 23 | 24 | to { 25 | transform: translate3d(0, 0, 0); 26 | } 27 | } 28 | 29 | @keyframes bounceOutUp { 30 | 20% { 31 | transform: translate3d(0, -10px, 0); 32 | } 33 | 34 | 40%, 45% { 35 | opacity: 1; 36 | transform: translate3d(0, 20px, 0); 37 | } 38 | 39 | to { 40 | opacity: 0; 41 | transform: translate3d(0, -2000px, 0); 42 | } 43 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/all.less: -------------------------------------------------------------------------------- 1 | @import 'fade'; 2 | @import 'fadeDown'; 3 | @import 'fadeDownBig'; 4 | @import 'fadeLeft'; 5 | @import 'fadeLeftBig'; 6 | @import 'fadeRight'; 7 | @import 'fadeRightBig'; 8 | @import 'fadeUp'; 9 | @import 'fadeUpBig'; 10 | 11 | @fades: Down, DownBig, Left, LeftBig, Right, RightBig, Up, UpBig; 12 | 13 | .make-transitions(fade, @fades); 14 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fade.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeIn { 2 | from { 3 | opacity: 0; 4 | } 5 | 6 | to { 7 | opacity: 1; 8 | } 9 | } 10 | 11 | @keyframes fadeOut { 12 | from { 13 | opacity: 1; 14 | } 15 | 16 | to { 17 | opacity: 0; 18 | } 19 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeDown.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInDown { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(0, -100%, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutDown { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(0, 100%, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeDownBig.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInDownBig { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(0, -2000px, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutDownBig { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(0, 2000px, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInLeft { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(-100%, 0, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutLeft { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(-100%, 0, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeLeftBig.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInLeftBig { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(-2000px, 0, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutLeftBig { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(-2000px, 0, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeRight.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInRight { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(100%, 0, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutRight { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(100%, 0, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeRightBig.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInRightBig { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(2000px, 0, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutRightBig { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(2000px, 0, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeUp.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInUp { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(0, 100%, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutUp { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(0, -100%, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/fading/fadeUpBig.less: -------------------------------------------------------------------------------- 1 | @keyframes fadeInUpBig { 2 | from { 3 | opacity: 0; 4 | transform: translate3d(0, 2000px, 0); 5 | } 6 | 7 | to { 8 | opacity: 1; 9 | transform: none; 10 | } 11 | } 12 | 13 | @keyframes fadeOutUp { 14 | from { 15 | opacity: 1; 16 | } 17 | 18 | to { 19 | opacity: 0; 20 | transform: translate3d(0, -100%, 0); 21 | } 22 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/all.less: -------------------------------------------------------------------------------- 1 | @import 'rotate'; 2 | @import 'rotateDownLeft'; 3 | @import 'rotateDownRight'; 4 | @import 'rotateUpLeft'; 5 | @import 'rotateUpRight'; 6 | 7 | @rotates: DownLeft, DownRight, UpLeft, UpRight; 8 | .make-transitions(rotate, @rotates); 9 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/rotate.less: -------------------------------------------------------------------------------- 1 | @keyframes rotateIn { 2 | from { 3 | transform-origin: center; 4 | transform: rotate3d(0, 0, 1, -200deg); 5 | opacity: 0; 6 | } 7 | 8 | to { 9 | transform-origin: center; 10 | transform: none; 11 | opacity: 1; 12 | } 13 | } 14 | 15 | @keyframes rotateOut { 16 | from { 17 | transform-origin: center; 18 | opacity: 1; 19 | } 20 | 21 | to { 22 | transform-origin: center; 23 | transform: rotate3d(0, 0, 1, 200deg); 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/rotateDownLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes rotateInDownLeft { 2 | from { 3 | transform-origin: left bottom; 4 | transform: rotate3d(0, 0, 1, -45deg); 5 | opacity: 0; 6 | } 7 | 8 | to { 9 | transform-origin: left bottom; 10 | transform: none; 11 | opacity: 1; 12 | } 13 | } 14 | 15 | @keyframes rotateOutDownLeft { 16 | from { 17 | transform-origin: left bottom; 18 | opacity: 1; 19 | } 20 | 21 | to { 22 | transform-origin: left bottom; 23 | transform: rotate3d(0, 0, 1, 45deg); 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/rotateDownRight.less: -------------------------------------------------------------------------------- 1 | @keyframes rotateInDownRight { 2 | from { 3 | transform-origin: right bottom; 4 | transform: rotate3d(0, 0, 1, 45deg); 5 | opacity: 0; 6 | } 7 | 8 | to { 9 | transform-origin: right bottom; 10 | transform: none; 11 | opacity: 1; 12 | } 13 | } 14 | 15 | @keyframes rotateOutDownRight { 16 | from { 17 | transform-origin: right bottom; 18 | opacity: 1; 19 | } 20 | 21 | to { 22 | transform-origin: right bottom; 23 | transform: rotate3d(0, 0, 1, -45deg); 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/rotateUpLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes rotateInUpLeft { 2 | from { 3 | transform-origin: left bottom; 4 | transform: rotate3d(0, 0, 1, 45deg); 5 | opacity: 0; 6 | } 7 | 8 | to { 9 | transform-origin: left bottom; 10 | transform: none; 11 | opacity: 1; 12 | } 13 | } 14 | 15 | @keyframes rotateOutUpLeft { 16 | from { 17 | transform-origin: left bottom; 18 | opacity: 1; 19 | } 20 | 21 | to { 22 | transform-origin: left bottom; 23 | transform: rotate3d(0, 0, 1, -45deg); 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/rotating/rotateUpRight.less: -------------------------------------------------------------------------------- 1 | @keyframes rotateInUpRight { 2 | from { 3 | transform-origin: right bottom; 4 | transform: rotate3d(0, 0, 1, -90deg); 5 | opacity: 0; 6 | } 7 | 8 | to { 9 | transform-origin: right bottom; 10 | transform: none; 11 | opacity: 1; 12 | } 13 | } 14 | 15 | @keyframes rotateOutUpRight { 16 | from { 17 | transform-origin: right bottom; 18 | opacity: 1; 19 | } 20 | 21 | to { 22 | transform-origin: right bottom; 23 | transform: rotate3d(0, 0, 1, 90deg); 24 | opacity: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/sliding/all.less: -------------------------------------------------------------------------------- 1 | @import 'slideDown'; 2 | @import 'slideLeft'; 3 | @import 'slideRight'; 4 | @import 'slideUp'; 5 | 6 | @slides: Down, Left, Right, Up; 7 | .make-transitions(slide, @slides); 8 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/sliding/slideDown.less: -------------------------------------------------------------------------------- 1 | @keyframes slideInDown { 2 | from { 3 | transform: translate3d(0, -100%, 0); 4 | visibility: visible; 5 | } 6 | 7 | to { 8 | transform: translate3d(0, 0, 0); 9 | } 10 | } 11 | 12 | @keyframes slideOutDown { 13 | from { 14 | transform: translate3d(0, 0, 0); 15 | } 16 | 17 | to { 18 | visibility: hidden; 19 | transform: translate3d(0, 100%, 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/sliding/slideLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes slideInLeft { 2 | from { 3 | transform: translate3d(-100%, 0, 0); 4 | visibility: visible; 5 | } 6 | 7 | to { 8 | transform: translate3d(0, 0, 0); 9 | } 10 | } 11 | 12 | @keyframes slideOutLeft { 13 | from { 14 | transform: translate3d(0, 0, 0); 15 | } 16 | 17 | to { 18 | visibility: hidden; 19 | transform: translate3d(-100%, 0, 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/sliding/slideRight.less: -------------------------------------------------------------------------------- 1 | @keyframes slideInRight { 2 | from { 3 | transform: translate3d(100%, 0, 0); 4 | visibility: visible; 5 | } 6 | 7 | to { 8 | transform: translate3d(0, 0, 0); 9 | } 10 | } 11 | 12 | @keyframes slideOutRight { 13 | from { 14 | transform: translate3d(0, 0, 0); 15 | } 16 | 17 | to { 18 | visibility: hidden; 19 | transform: translate3d(100%, 0, 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/sliding/slideUp.less: -------------------------------------------------------------------------------- 1 | @keyframes slideInUp { 2 | from { 3 | transform: translate3d(0, 100%, 0); 4 | visibility: visible; 5 | } 6 | 7 | to { 8 | transform: translate3d(0, 0, 0); 9 | } 10 | } 11 | 12 | @keyframes slideOutUp { 13 | from { 14 | transform: translate3d(0, 0, 0); 15 | } 16 | 17 | to { 18 | visibility: hidden; 19 | transform: translate3d(0, -100%, 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/all.less: -------------------------------------------------------------------------------- 1 | @import 'zoom'; 2 | @import 'zoomDown'; 3 | @import 'zoomLeft'; 4 | @import 'zoomRight'; 5 | @import 'zoomUp'; 6 | 7 | @zooms: Down, Left, Right, Up; 8 | .make-transitions(zoom, @zooms); 9 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/zoom.less: -------------------------------------------------------------------------------- 1 | @keyframes zoomIn { 2 | from { 3 | opacity: 0; 4 | transform: scale3d(.3, .3, .3); 5 | } 6 | 7 | 50% { 8 | opacity: 1; 9 | } 10 | } 11 | 12 | @keyframes zoomOut { 13 | from { 14 | opacity: 1; 15 | } 16 | 17 | 50% { 18 | opacity: 0; 19 | transform: scale3d(.3, .3, .3); 20 | } 21 | 22 | to { 23 | opacity: 0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/zoomDown.less: -------------------------------------------------------------------------------- 1 | @keyframes zoomInDown { 2 | from { 3 | opacity: 0; 4 | transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); 5 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 6 | } 7 | 8 | 60% { 9 | opacity: 1; 10 | transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); 11 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 12 | } 13 | } 14 | 15 | @keyframes zoomOutDown { 16 | 40% { 17 | opacity: 1; 18 | transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); 19 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 20 | } 21 | 22 | to { 23 | opacity: 0; 24 | transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); 25 | transform-origin: center bottom; 26 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/zoomLeft.less: -------------------------------------------------------------------------------- 1 | @keyframes zoomInLeft { 2 | from { 3 | opacity: 0; 4 | transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); 5 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 6 | } 7 | 8 | 60% { 9 | opacity: 1; 10 | transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); 11 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 12 | } 13 | } 14 | 15 | @keyframes zoomOutLeft { 16 | 40% { 17 | opacity: 1; 18 | transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); 19 | } 20 | 21 | to { 22 | opacity: 0; 23 | transform: scale(.1) translate3d(-2000px, 0, 0); 24 | transform-origin: left center; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/zoomRight.less: -------------------------------------------------------------------------------- 1 | @keyframes zoomInRight { 2 | from { 3 | opacity: 0; 4 | transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); 5 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 6 | } 7 | 8 | 60% { 9 | opacity: 1; 10 | transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); 11 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 12 | } 13 | } 14 | 15 | @keyframes zoomOutRight { 16 | 40% { 17 | opacity: 1; 18 | transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); 19 | } 20 | 21 | to { 22 | opacity: 0; 23 | transform: scale(.1) translate3d(2000px, 0, 0); 24 | transform-origin: right center; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/animations/zooming/zoomUp.less: -------------------------------------------------------------------------------- 1 | @keyframes zoomInUp { 2 | from { 3 | opacity: 0; 4 | transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); 5 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 6 | } 7 | 8 | 60% { 9 | opacity: 1; 10 | transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); 11 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 12 | } 13 | } 14 | 15 | @keyframes zoomOutUp { 16 | 40% { 17 | opacity: 1; 18 | transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); 19 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190); 20 | } 21 | 22 | to { 23 | opacity: 0; 24 | transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); 25 | transform-origin: center bottom; 26 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/make-transitions.less: -------------------------------------------------------------------------------- 1 | .make-transitions(@base, @names) { 2 | 3 | // We'll make a single rule for all transitions that 4 | // sets the animation duration. This is basically the 5 | // stock 'animate' class from Animate.css. 6 | @classesJoin: replace(~'@{names}', ', ', '-enter-active, .@{base}', g); 7 | 8 | //.@{base}-enter-active, .@{base}-leave-active, 9 | //.@{base}@{classesJoin}-leave-active { 10 | // animation-duration: @animationDuration; 11 | // animation-fill-mode: both; 12 | //} 13 | 14 | .@{base}-enter-active, .@{base}In, 15 | .@{base}-leave-active, .@{base}Out { 16 | animation-duration: @animationDuration; 17 | animation-fill-mode: both; 18 | } 19 | 20 | // Entrance/Exit for the base class 21 | .@{base}-enter-active, .@{base}In { 22 | animation-name: ~'@{base}In'; 23 | } 24 | 25 | .@{base}-leave-active, .@{base}Out { 26 | animation-name: ~'@{base}Out'; 27 | } 28 | 29 | // Loop through the different animations, and set 30 | // the enter/leave animation names for each class. 31 | .-(@i: length(@names)) when (@i > 0) { 32 | 33 | @name: extract(@names, @i); 34 | .@{base}@{name}-enter-active, .@{base}In@{name}, 35 | .@{base}@{name}-leave-active, .@{base}Out@{name} { 36 | animation-duration: @animationDuration; 37 | animation-fill-mode: both; 38 | } 39 | 40 | .@{base}@{name}-enter-active, .@{base}In@{name} { 41 | animation-name: ~'@{base}In@{name}'; 42 | } 43 | .@{base}@{name}-leave-active, .@{base}Out@{name} { 44 | animation-name: ~'@{base}Out@{name}'; 45 | } 46 | .-((@i - 1)); 47 | 48 | } .-; 49 | } -------------------------------------------------------------------------------- /src/assets/styles/vendor/vue2-animate/src/vue2-animate.less: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | /*! 4 | * vue2-animate v1.0.4 5 | * (c) 2016 Simon Asika 6 | * Released under the MIT License. 7 | * Documentation: https://github.com/asika32764/vue2-animate 8 | */ 9 | 10 | @animationDuration: 1s; 11 | @animations: './animations'; 12 | 13 | // Main mixin 14 | @import "make-transitions"; 15 | 16 | // Our animations 17 | @import "@{animations}/bouncing/all"; 18 | @import "@{animations}/fading/all"; 19 | @import "@{animations}/rotating/all"; 20 | @import "@{animations}/sliding/all"; 21 | @import "@{animations}/zooming/all"; 22 | -------------------------------------------------------------------------------- /src/assets/telasapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/assets/telasapp.png -------------------------------------------------------------------------------- /src/common/directives/masks.js: -------------------------------------------------------------------------------- 1 | import Cleave from 'cleave.js'; 2 | 3 | const hour = { 4 | date: true, 5 | datePattern: ['h', 'mm'], 6 | delimiter: ':', 7 | }; 8 | 9 | const date = { 10 | date: true, 11 | datePattern: ['m', 'd', 'Y'], 12 | }; 13 | 14 | const phone = { 15 | phone: true, 16 | phoneRegionCode: 'BR', 17 | }; 18 | 19 | const money = { 20 | // numeral: true, 21 | delimiters: [',', ',', '.'], 22 | blocks: [3, 3, 2], 23 | }; 24 | 25 | /* eslint-disable no-new */ 26 | export const vHour = { 27 | bind() { 28 | new Cleave(this.el, hour); 29 | }, 30 | }; 31 | 32 | export const vDate = { 33 | bind(el) { 34 | new Cleave(el, date); 35 | }, 36 | }; 37 | 38 | export const vPhone = { 39 | bind(el) { 40 | new Cleave(el, phone); 41 | }, 42 | }; 43 | 44 | export const vMoney = { 45 | bind(el) { 46 | new Cleave(el, money); 47 | }, 48 | }; 49 | -------------------------------------------------------------------------------- /src/common/filters/goals.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/common/filters/goals.js -------------------------------------------------------------------------------- /src/common/functions/fun.js: -------------------------------------------------------------------------------- 1 | export const formatCurrency = (n, currency = '$') => `${currency} ${n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')}`; 2 | 3 | export const animateCount = (number, target) => { 4 | const interval = setInterval(() => { 5 | if (number >= target) { 6 | clearInterval(interval); 7 | return; 8 | } 9 | number += 1; 10 | }, 1); 11 | }; 12 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue'; 4 | import Vuex from 'vuex'; 5 | import Router from 'vue-router'; 6 | import VueResource from 'vue-resource'; 7 | import { sync } from 'vuex-router-sync'; 8 | 9 | import App from './App'; 10 | import VuexStore from './vuex/store'; 11 | import { routes } from './router-config'; 12 | 13 | import { 14 | vDate, 15 | vMoney, 16 | } from './common/directives/masks'; 17 | 18 | Vue.use(Vuex); 19 | Vue.use(Router); 20 | Vue.use(VueResource); 21 | 22 | Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'; 23 | 24 | Vue.directive('date', vDate); 25 | Vue.directive('money', vMoney); 26 | 27 | const store = new Vuex.Store(VuexStore); 28 | 29 | const router = new Router({ 30 | routes, 31 | mode: 'history', 32 | saveScrollPosition: true, 33 | }); 34 | 35 | sync(store, router); 36 | 37 | /* eslint-disable no-unused-vars */ 38 | const app = new Vue({ 39 | router, 40 | store, 41 | render: h => h(App), 42 | }).$mount('#app'); 43 | -------------------------------------------------------------------------------- /src/router-config.js: -------------------------------------------------------------------------------- 1 | import Login from './spa/Login'; 2 | import Home from './spa/Home'; 3 | import Dash from './spa/Dash/Dash'; 4 | import Goal from './spa/Goal/Goal'; 5 | import Notifications from './spa/Goal/Notifications'; 6 | import EditGoal from './spa/Goal/Edit'; 7 | 8 | import database from './vuex/database'; 9 | 10 | /* eslint-disable import/prefer-default-export */ 11 | export const routes = [ 12 | { 13 | path: '/', 14 | component: Home, 15 | redirect: '/dash', 16 | children: [ 17 | { 18 | path: 'dash', 19 | name: 'dash', 20 | component: Dash, 21 | }, 22 | { 23 | path: 'goal/:id', 24 | name: 'goal', 25 | component: Goal, 26 | }, 27 | { 28 | path: 'goal/:id/notifications', 29 | name: 'goal-notifications', 30 | component: Notifications, 31 | }, 32 | { 33 | path: 'goal/:id/edit', 34 | name: 'goal-edit', 35 | component: EditGoal, 36 | }, 37 | ], 38 | }, 39 | { 40 | path: '/forbidden', 41 | name: 'forbidden', 42 | component: Home, 43 | }, 44 | { 45 | path: '/login', 46 | name: 'login', 47 | component: Login, 48 | }, 49 | ]; 50 | 51 | const createDatabaseIfNotExists = () => { 52 | database.getDoc('goals') 53 | .catch(() => database.persist()); 54 | }; 55 | 56 | export const routesConfig = (to) => { 57 | if (to.path === '/logout') { 58 | database.destroyDatabase() 59 | .then(() => { 60 | to.path = '/login'; 61 | }); 62 | } else { 63 | createDatabaseIfNotExists(); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /src/shared-components/ActionBar.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 72 | 73 | 84 | -------------------------------------------------------------------------------- /src/shared-components/Chart.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 88 | -------------------------------------------------------------------------------- /src/shared-components/GeneralNotifications.vue: -------------------------------------------------------------------------------- 1 | 121 | 122 | 140 | 141 | 180 | -------------------------------------------------------------------------------- /src/shared-components/Hello.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 35 | 54 | -------------------------------------------------------------------------------- /src/shared-components/Loading.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | 27 | 45 | -------------------------------------------------------------------------------- /src/shared-components/Navigation.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 49 | 50 | 81 | -------------------------------------------------------------------------------- /src/shared-components/Range.vue: -------------------------------------------------------------------------------- 1 | 97 | 98 | 125 | 126 | 196 | -------------------------------------------------------------------------------- /src/shared-components/Selector.vue: -------------------------------------------------------------------------------- 1 | 83 | 84 | 112 | 113 | 156 | -------------------------------------------------------------------------------- /src/spa/Dash/Dash.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 126 | 127 | 149 | -------------------------------------------------------------------------------- /src/spa/Dash/Item.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 77 | 78 | 115 | -------------------------------------------------------------------------------- /src/spa/Dash/RegisterModal.vue: -------------------------------------------------------------------------------- 1 | 105 | 106 | 224 | 225 | 327 | -------------------------------------------------------------------------------- /src/spa/Forbidden/Forbidden.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/spa/Forbidden/Forbidden.vue -------------------------------------------------------------------------------- /src/spa/Goal/Edit.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 134 | 135 | 191 | -------------------------------------------------------------------------------- /src/spa/Goal/Goal.vue: -------------------------------------------------------------------------------- 1 | 144 | 145 | 191 | 192 | 295 | -------------------------------------------------------------------------------- /src/spa/Goal/NewGoal.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 25 | -------------------------------------------------------------------------------- /src/spa/Goal/Notifications.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 59 | 60 | 96 | -------------------------------------------------------------------------------- /src/spa/Goal/SubGoalModal.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 46 | 47 | 76 | -------------------------------------------------------------------------------- /src/spa/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 25 | -------------------------------------------------------------------------------- /src/spa/Landing/Landing.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 68 | 69 | 164 | -------------------------------------------------------------------------------- /src/spa/Login.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 25 | -------------------------------------------------------------------------------- /src/spa/Login/Login.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/src/spa/Login/Login.vue -------------------------------------------------------------------------------- /src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | import * as mutations from './mutation-types'; 2 | /* eslint-disable import/prefer-default-export */ 3 | 4 | /** 5 | * Category Actions 6 | */ 7 | export const setUser = ({ commit }, data) => commit(mutations.USER_OBJECT, data); 8 | 9 | export const setGoal = ({ commit }, data) => commit(mutations.GOAL_OBJECT, data); 10 | export const setGoalCollection = ({ commit }, data) => commit(mutations.GOAL_COLLECTION, data); 11 | 12 | export const setLoader = ({ commit }, data) => commit(mutations.LOAGING_STATE, data); 13 | 14 | export const setNotificationsBarStatus = ({ commit }, status) => 15 | commit(mutations.SET_NOTIFICATIONS_BAR_STATUS, status); 16 | -------------------------------------------------------------------------------- /src/vuex/database.js: -------------------------------------------------------------------------------- 1 | import PouchDB from 'pouchdb'; 2 | 3 | // import memory from 'pouchdb/extras/memory'; 4 | 5 | const pouchDBName = 'goaldatabase', 6 | // pouchDBDefaultOptions = { adapter: 'memory', auto_compaction: true }, 7 | pouchDBDefaultOptions = { 8 | adapter: 'websql', 9 | auto_compaction: true, 10 | }, 11 | adaptersFallback = [ 12 | 'idb', 13 | 'websql', 14 | 'leveldb', 15 | 'http', 16 | ]; 17 | 18 | // export const camelize = (string) => string.replace(/_\w/g, (m) => m[1].toUpperCase()); 19 | 20 | export default { 21 | database: new PouchDB(pouchDBName, pouchDBDefaultOptions), 22 | 23 | persist() { 24 | const persistDBOptions = { 25 | adapter: 'websql', 26 | auto_compaction: true, 27 | }; 28 | 29 | for (let index = 0, total = adaptersFallback.length; index < total; index += 1) { 30 | persistDBOptions.adapter = adaptersFallback[index]; 31 | this.database = new PouchDB(pouchDBName, persistDBOptions); 32 | if (this.database) { 33 | break; 34 | } 35 | } 36 | 37 | if (!this.database) { 38 | this.database = new PouchDB(pouchDBName, { auto_compaction: true }); 39 | } 40 | 41 | return this; 42 | }, 43 | 44 | putDoc(key = null, data = null) { 45 | if (!key || !data) { 46 | throw Error('GoalDatabase: Neither key nor data can be null'); 47 | } 48 | 49 | this.getDoc(key) 50 | /* eslint-disable */ 51 | .then(doc => this.database.put({ _id: key, _rev: doc._rev, data })) 52 | /* eslint-enable */ 53 | .catch(() => 54 | this.database.put({ _id: key, data }) 55 | .then(success => success) 56 | .catch((err) => { 57 | throw Error(`GoalDatabase: ${err}`); 58 | }) 59 | ); 60 | return this; 61 | }, 62 | 63 | getDoc(key) { 64 | return this.database.get(key); 65 | }, 66 | 67 | getAll() { 68 | return this.database.allDocs({ 69 | include_docs: true, 70 | attachments: true, 71 | }); 72 | }, 73 | 74 | deleteDoc(key) { 75 | return this.database.remove(key); 76 | }, 77 | 78 | destroyDatabase() { 79 | return this.database.destroy(); 80 | }, 81 | }; 82 | -------------------------------------------------------------------------------- /src/vuex/getters.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | export const getGoalObject = state => state.goal.goal; 3 | export const getGoalCollection = state => state.goal.goals; 4 | 5 | export const getUserObject = state => state.user.user; 6 | 7 | export const getLoader = state => state.loader.loading; 8 | 9 | export const getNotificationsBarStatus = state => 10 | state.notifications.notificationsBarStatus; 11 | -------------------------------------------------------------------------------- /src/vuex/modules/goal.js: -------------------------------------------------------------------------------- 1 | import { 2 | GOAL_OBJECT, 3 | GOAL_COLLECTION, 4 | } from '../mutation-types'; 5 | 6 | const mutations = { 7 | [GOAL_OBJECT](state, data) { 8 | if (data && typeof data === 'object') { 9 | state.goal = data; 10 | } 11 | }, 12 | [GOAL_COLLECTION](state, data) { 13 | if (data && typeof data === 'object' && data.length) { 14 | state.goals = data; 15 | } 16 | }, 17 | }; 18 | 19 | const state = { 20 | goal: { 21 | dueDate: '', 22 | description: '', 23 | icon: '', 24 | name: '', 25 | value: 0, 26 | reservedBalance: 0, 27 | }, 28 | goals: [], 29 | }; 30 | 31 | export default { 32 | state, 33 | mutations, 34 | }; 35 | -------------------------------------------------------------------------------- /src/vuex/modules/loader.js: -------------------------------------------------------------------------------- 1 | import { 2 | LOAGING_STATE, 3 | } from '../mutation-types'; 4 | 5 | const mutations = { 6 | [LOAGING_STATE](state, data) { 7 | if (typeof data === 'boolean') { 8 | state.loading = data; 9 | } 10 | }, 11 | }; 12 | 13 | const state = { 14 | loading: false, 15 | }; 16 | 17 | export default { 18 | state, 19 | mutations, 20 | }; 21 | -------------------------------------------------------------------------------- /src/vuex/modules/notifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | NOTIFICATIONS_OBJECT, 3 | NOTIFICATIONS_COLLECTION, 4 | SET_NOTIFICATIONS_BAR_STATUS, 5 | } from '../mutation-types'; 6 | 7 | const mutations = { 8 | [NOTIFICATIONS_OBJECT](state, data) { 9 | if (data && typeof data === 'object') { 10 | state.goal = data; 11 | } 12 | }, 13 | [NOTIFICATIONS_COLLECTION](state, data) { 14 | if (data && typeof data === 'object' && data.length) { 15 | state.goal = data; 16 | } 17 | }, 18 | [SET_NOTIFICATIONS_BAR_STATUS](state, status) { 19 | state.notificationsBarStatus = status; 20 | }, 21 | }; 22 | 23 | const state = { 24 | notification: { 25 | date: '', 26 | message: '', 27 | }, 28 | notifications: [], 29 | notificationsBarStatus: false, 30 | }; 31 | 32 | export default { 33 | state, 34 | mutations, 35 | }; 36 | -------------------------------------------------------------------------------- /src/vuex/modules/subgoals.js: -------------------------------------------------------------------------------- 1 | import { 2 | SUBGOAL_OBJECT, 3 | SUBGOAL_COLLECTION, 4 | } from '../mutation-types'; 5 | 6 | const mutations = { 7 | [SUBGOAL_OBJECT](state, data) { 8 | if (data && typeof data === 'object') { 9 | state.goal = data; 10 | } 11 | }, 12 | [SUBGOAL_COLLECTION](state, data) { 13 | if (data && typeof data === 'object' && data.length) { 14 | state.goal = data; 15 | } 16 | }, 17 | }; 18 | 19 | const state = { 20 | subgoal: { 21 | id: -1, 22 | name: '', 23 | value: 0, 24 | reservedBalance: 0, 25 | }, 26 | subgoals: [], 27 | }; 28 | 29 | export default { 30 | state, 31 | mutations, 32 | }; 33 | -------------------------------------------------------------------------------- /src/vuex/modules/user.js: -------------------------------------------------------------------------------- 1 | import { 2 | USER_OBJECT, 3 | } from '../mutation-types'; 4 | 5 | const mutations = { 6 | [USER_OBJECT](state, data) { 7 | if (data && typeof data === 'object') { 8 | state.user = data; 9 | } 10 | }, 11 | }; 12 | 13 | const state = { 14 | user: { 15 | userId: -1, 16 | userName: '', 17 | balance: 0, 18 | goals: [], 19 | }, 20 | }; 21 | 22 | export default { 23 | state, 24 | mutations, 25 | }; 26 | -------------------------------------------------------------------------------- /src/vuex/mutation-types.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | export const USER_OBJECT = 'USER_OBJECT'; 3 | 4 | export const LOAGING_STATE = 'LOAGING_STATE'; 5 | 6 | export const GOAL_OBJECT = 'GOAL_OBJECT'; 7 | export const GOAL_COLLECTION = 'GOAL_COLLECTION'; 8 | 9 | export const SUBGOAL_OBJECT = 'SUBGOAL_OBJECT'; 10 | export const SUBGOAL_COLLECTION = 'SUBGOAL_COLLECTION'; 11 | 12 | export const NOTIFICATIONS_OBJECT = 'NOTIFICATIONS_OBJECT'; 13 | export const NOTIFICATIONS_COLLECTION = 'NOTIFICATIONS_COLLECTION'; 14 | -------------------------------------------------------------------------------- /src/vuex/resources.js: -------------------------------------------------------------------------------- 1 | const basePath = 'http://tnkajgsyxadfyykqw.stoplight-proxy.io/api'; 2 | 3 | const loginActions = { 4 | login: { method: 'POST', url: `${basePath}/login` }, 5 | }; 6 | export const loginResource = resource => resource(`${basePath}/login`, {}, loginActions); 7 | 8 | const goalsActions = { 9 | getGoals: { method: 'GET', url: `${basePath}/goals/user{/id}` }, 10 | persistGoal: { method: 'POST', url: `${basePath}/goals/user{/id}` }, 11 | updateGoal: { method: 'PUT', url: `${basePath}/goal/{goalid}/user/{userid}` }, 12 | removeGoal: { method: 'DELETE', url: `${basePath}/goal/{goalid}/user/{userid}` }, 13 | finishGoal: { method: 'PUT', url: `${basePath}/goal/{goalid}/user/{userid}/finish` }, 14 | }; 15 | export const goalsResource = resource => resource(`${basePath}/goals/user{/id}`, {}, goalsActions); 16 | 17 | const subGoalsActions = { 18 | getSubGoals: { method: 'GET', url: `${basePath}/goals/{goalid}/subgoals` }, 19 | persistSubGoals: { method: 'POST', url: `${basePath}/goals/{goalid}/subgoals` }, 20 | updateSubGoals: { method: 'PUT', url: `${basePath}/goals/{goalid}/subgoals/{subgoalid} ` }, 21 | removeSubGoals: { method: 'DELETE', url: `${basePath}/goals/{goalid}/subgoals/{subgoalid} ` }, 22 | }; 23 | export const subGoalsResource = resource => resource(`${basePath}/goals/{goalid}/subgoals`, {}, subGoalsActions); 24 | 25 | const notificationsActions = { 26 | getGoalNotifications: { method: 'GET', url: `${basePath}/notification/user/{userId}/goal/{goalId}` }, 27 | getGeneralNotifications: { method: 'GET', url: `${basePath}/notification/user/{userId}` }, 28 | }; 29 | export const notificationsResource = resource => resource(`${basePath}/notification/user/{userId}`, {}, notificationsActions); 30 | -------------------------------------------------------------------------------- /src/vuex/store.js: -------------------------------------------------------------------------------- 1 | import goal from './modules/goal'; 2 | import loader from './modules/loader'; 3 | import notifications from './modules/notifications'; 4 | import subgoals from './modules/subgoals'; 5 | import user from './modules/user'; 6 | 7 | import * as actions from './actions'; 8 | import * as getters from './getters'; 9 | 10 | // A Vuex instance is created by combining the state, the actions, 11 | // and the mutations. Because the actions and mutations are just 12 | // functions that do not depend on the instance itself, they can 13 | // be easily tested or even hot-reloaded (see counter-hot example). 14 | 15 | export default { 16 | actions, 17 | getters, 18 | modules: { 19 | goal, 20 | loader, 21 | notifications, 22 | subgoals, 23 | user, 24 | }, 25 | strict: true, 26 | }; 27 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablohpsilva/Goal/a4ca3dcd539f1d1bae472b324e1b425aab5ebf63/static/.gitkeep -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/guide#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": "node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar", 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 | -------------------------------------------------------------------------------- /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 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2); 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']); 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']); 18 | } 19 | 20 | var spawn = require('cross-spawn'); 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }); 22 | 23 | runner.on('exit', function (code) { 24 | server.close(); 25 | process.exit(code); 26 | }); 27 | 28 | runner.on('error', function (err) { 29 | server.close(); 30 | throw err; 31 | }); 32 | -------------------------------------------------------------------------------- /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 test(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 App') 16 | .assert.elementCount('img', 1) 17 | .end(); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind'); 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/); 7 | testsContext.keys().forEach(testsContext); 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/); 13 | srcContext.keys().forEach(srcContext); 14 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var path = require('path'); 7 | var merge = require('webpack-merge'); 8 | var baseConfig = require('../../build/webpack.base.conf'); 9 | var utils = require('../../build/utils'); 10 | var webpack = require('webpack'); 11 | var projectRoot = path.resolve(__dirname, '../../'); 12 | 13 | var webpackConfig = merge(baseConfig, { 14 | // use inline sourcemap for karma-sourcemap-loader 15 | module: { 16 | loaders: utils.styleLoaders() 17 | }, 18 | devtool: '#inline-source-map', 19 | vue: { 20 | loaders: { 21 | js: 'isparta' 22 | } 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': require('../../config/test.env') 27 | }) 28 | ] 29 | }); 30 | 31 | // no need for app entry during tests 32 | delete webpackConfig.entry; 33 | 34 | // make sure isparta loader is applied before eslint 35 | webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || []; 36 | webpackConfig.module.preLoaders.unshift({ 37 | test: /\.js$/, 38 | loader: 'isparta', 39 | include: path.resolve(projectRoot, 'src'), 40 | }); 41 | 42 | // only apply babel for test files when using isparta 43 | webpackConfig.module.loaders.some(function (loader, i) { 44 | if (loader.loader === 'babel') { 45 | loader.include = path.resolve(projectRoot, 'test/unit'); 46 | return true; 47 | } 48 | }); 49 | 50 | module.exports = function (config) { 51 | config.set({ 52 | // to run in additional browsers: 53 | // 1. install corresponding karma launcher 54 | // http://karma-runner.github.io/0.13/config/browsers.html 55 | // 2. add it to the `browsers` array below. 56 | browsers: ['PhantomJS'], 57 | frameworks: ['mocha', 'sinon-chai'], 58 | reporters: ['spec', 'coverage'], 59 | files: ['./index.js'], 60 | preprocessors: { 61 | './index.js': ['webpack', 'sourcemap'] 62 | }, 63 | webpack: webpackConfig, 64 | webpackMiddleware: { 65 | noInfo: true, 66 | }, 67 | coverageReporter: { 68 | dir: './coverage', 69 | reporters: [ 70 | { type: 'lcov', subdir: '.' }, 71 | { type: 'text-summary' }, 72 | ] 73 | }, 74 | }); 75 | }; 76 | -------------------------------------------------------------------------------- /test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Hello from 'src/components/Hello'; 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | el: document.createElement('div'), 8 | render: (h) => h(Hello), 9 | }); 10 | expect(vm.$el.querySelector('.hello h1').textContent) 11 | .to.equal('Welcome to Your Vue.js App'); 12 | }); 13 | }); 14 | --------------------------------------------------------------------------------