├── .babelrc
├── src
├── assets
│ └── logo.png
├── products.json
├── App.vue
├── main.js
├── components
│ ├── ProductList.vue
│ ├── NavBar.vue
│ └── ShoppingCart.vue
└── store
│ └── store.js
├── .gitignore
├── README.md
├── index.html
├── package.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/connor11528/vue-shopping-cart/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log
5 | yarn-error.log
6 |
7 | # Editor directories and files
8 | .idea
9 | *.suo
10 | *.ntvs*
11 | *.njsproj
12 | *.sln
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-shopping-cart
2 |
3 | > shopping cart made with vue.js
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run watch
13 |
14 | # build for production with minification
15 | npm run prod
16 | ```
17 |
18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader).
19 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-shopping-cart
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/products.json:
--------------------------------------------------------------------------------
1 | [
2 | { "id": 1, "name": "Tshirt", "price": 3050, "quantity": 2, "sku": 1, "images": ["https://cdn.shopify.com/s/files/1/2415/9707/products/Screen_Shot_2017-10-02_at_10.18.11_AM_grande.png?v=1506964811"] },
3 | { "id": 2, "name": "Hat", "price": 2000, "quantity": 10, "sku": 2, "images": ["https://cdn.shopify.com/s/files/1/2415/9707/products/Screen_Shot_2017-10-02_at_10.23.01_AM_grande.png"] },
4 | { "id": 3, "name": "Stickers", "price": 550, "quantity": 5, "sku": 3, "images": ["https://cdn.shopify.com/s/files/1/2415/9707/products/logo_grande.png?v=1506964542"] }
5 | ]
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Product List
7 |
8 |
9 |
10 | Shopping Cart
11 |
12 | Total Cost: {{ totalCost | currency }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
31 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import Element from 'element-ui'
4 | import locale from 'element-ui/lib/locale/lang/en'
5 | import 'element-ui/lib/theme-default/index.css'
6 |
7 | import NavBar from './components/NavBar.vue'
8 | import ProductList from './components/ProductList.vue'
9 | import ShoppingCart from './components/ShoppingCart.vue'
10 |
11 | // Services
12 | Vue.use(Element, { locale })
13 |
14 | // Components
15 | Vue.component('NavBar', NavBar)
16 | Vue.component('ProductList', ProductList)
17 | Vue.component('ShoppingCart', ShoppingCart)
18 |
19 | // Filters
20 | Vue.filter('currency', function (value) {
21 | return '$' + parseFloat(value/100).toFixed(2);
22 | });
23 |
24 | new Vue({
25 | el: '#app',
26 | render: h => h(App)
27 | })
28 |
--------------------------------------------------------------------------------
/src/components/ProductList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ product.name }}
7 | {{ product.price | currency }}
8 |
9 | Add to cart
10 |
11 |
12 |
13 |
14 |
15 |
16 |
32 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-shopping-cart",
3 | "description": "shopping cart made with vue.js",
4 | "version": "1.0.0",
5 | "author": "Connor Leech ",
6 | "private": true,
7 | "scripts": {
8 | "watch": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
9 | "prod": "cross-env NODE_ENV=production webpack --progress --hide-modules"
10 | },
11 | "dependencies": {
12 | "element-ui": "^1.4.6",
13 | "vue": "^2.4.4"
14 | },
15 | "devDependencies": {
16 | "babel-core": "^6.26.0",
17 | "babel-loader": "^7.1.2",
18 | "babel-preset-env": "^1.6.0",
19 | "babel-preset-vue-app": "^1.3.1",
20 | "cross-env": "^5.0.5",
21 | "css-loader": "^0.28.7",
22 | "file-loader": "^1.1.4",
23 | "node-sass": "^4.5.3",
24 | "sass-loader": "^6.0.6",
25 | "style-loader": "^0.19.0",
26 | "vue-loader": "^13.0.5",
27 | "vue-template-compiler": "^2.4.4",
28 | "webpack": "^3.6.0",
29 | "webpack-dev-server": "^2.9.1"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/store/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import products from '../products'
3 |
4 | export const Store = new Vue({
5 | data() {
6 | return {
7 | products,
8 | cart: []
9 | };
10 | },
11 | computed: {
12 | totalCost(){
13 | return this.cart.reduce((accum, product) => {
14 | return accum + product.details.price * product.quantity
15 | }, 0)
16 | }
17 | },
18 | methods: {
19 | addToCart(product){
20 | const locationInCart = this.cart.findIndex(p => {
21 | return p.details.sku === product.sku
22 | })
23 |
24 | if (locationInCart === -1) {
25 | this.cart.push({
26 | details: product,
27 | quantity: 1
28 | })
29 | } else {
30 | this.cart[locationInCart].quantity++
31 | }
32 | },
33 | removeFromCart(sku){
34 | const locationInCart = this.cart.findIndex(p => {
35 | return p.details.sku === sku
36 | })
37 |
38 | if(this.cart[locationInCart].quantity <= 1){
39 | this.cart.splice(locationInCart, 1)
40 | } else {
41 | this.cart[locationInCart].quantity--
42 | }
43 | }
44 | }
45 | });
--------------------------------------------------------------------------------
/src/components/ShoppingCart.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
11 |
12 | {{ scope.row.details.price | currency }}
13 |
14 |
15 |
18 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
47 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | entry: './src/main.js',
6 | output: {
7 | path: path.resolve(__dirname, './dist'),
8 | publicPath: '/dist/',
9 | filename: 'build.js'
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.vue$/,
15 | loader: 'vue-loader',
16 | options: {
17 | loaders: {
18 | // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
19 | // the "scss" and "sass" values for the lang attribute to the right configs here.
20 | // other preprocessors should work out of the box, no loader config like this necessary.
21 | 'scss': 'vue-style-loader!css-loader!sass-loader',
22 | 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
23 | }
24 | // other vue-loader options go here
25 | }
26 | },
27 | {
28 | test: /\.js$/,
29 | loader: 'babel-loader',
30 | exclude: /node_modules/
31 | },
32 | {
33 | test: /\.css$/,
34 | loader: 'style-loader!css-loader'
35 | },
36 | {
37 | test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
38 | loader: 'file-loader'
39 | },
40 | {
41 | test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
42 | loader: 'file-loader',
43 | query: {
44 | name: '[name].[ext]?[hash]'
45 | }
46 | }
47 | ]
48 | },
49 | resolve: {
50 | alias: {
51 | 'vue$': 'vue/dist/vue.esm.js'
52 | }
53 | },
54 | devServer: {
55 | historyApiFallback: true,
56 | noInfo: true
57 | },
58 | performance: {
59 | hints: false
60 | },
61 | devtool: '#eval-source-map'
62 | }
63 |
64 | if (process.env.NODE_ENV === 'production') {
65 | module.exports.devtool = '#source-map'
66 | // http://vue-loader.vuejs.org/en/workflow/production.html
67 | module.exports.plugins = (module.exports.plugins || []).concat([
68 | new webpack.DefinePlugin({
69 | 'process.env': {
70 | NODE_ENV: '"production"'
71 | }
72 | }),
73 | new webpack.optimize.UglifyJsPlugin({
74 | sourceMap: true,
75 | compress: {
76 | warnings: false
77 | }
78 | }),
79 | new webpack.LoaderOptionsPlugin({
80 | minimize: true
81 | })
82 | ])
83 | }
84 |
--------------------------------------------------------------------------------