diff --git a/.env_sample b/.env_sample index 91f1b735..451f8238 100644 --- a/.env_sample +++ b/.env_sample @@ -1,3 +1,7 @@ IMGUR_CLIENT_ID=x PORT=3000 NODE_ENV=development +PUSHER_APP_ID= +PUSHER_KEY= +PUSHER_SECRET= +PUSHER_CLUSTER= diff --git a/index.html b/index.html index 52365f64..a5ad48e6 100644 --- a/index.html +++ b/index.html @@ -2,29 +2,68 @@ - Codestin Search App - + + - + -
+

Vue.js Poster Store

+
-

Products go here.

+
Loading...
+
+ Found {{ results.length }} results for search term {{ lastSearch }}. +
+
+
+
+ +
+
+
+

{{ item.title }}

+

Price: {{ price | currency }}

+ +
+
+
+
No more items.
+

Shopping Cart

-
+ +
  • +
    {{ item.title }}
    +
    + + {{ item.price | currency }} x {{ item.qty }} + + + +
    +
  • +
    + +
    +
    Total: {{ total | currency }}
    +
    +
    +
    No items in the cart.
    @@ -33,7 +72,11 @@

    Shopping Cart

    - + + + + + diff --git a/index.js b/index.js index d0faddba..cfd2149b 100644 --- a/index.js +++ b/index.js @@ -4,9 +4,17 @@ var path = require('path'); var server = require('http').createServer(app); var axios = require('axios'); var querystring = require('querystring'); +var Pusher = require('pusher'); require('dotenv').config(); +var pusher = new Pusher({ + appId: process.env.PUSHER_APP_ID, + key: process.env.PUSHER_KEY, + secret: process.env.PUSHER_SECRET, + cluster: process.env.PUSHER_CLUSTER +}); + var bodyParser = require('body-parser'); app.use( bodyParser.json() ); @@ -31,6 +39,10 @@ app.get('/search/:query', function(req, res) { ; }); +app.post('/cart_update', function(req, res) { + pusher.trigger('cart', 'update', req.body); +}); + app.use('/node_modules', express.static(path.join(__dirname, 'node_modules'))); app.use('/public', express.static(path.join(__dirname, 'public'))); diff --git a/package.json b/package.json index 679e9eba..a584e3f6 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,8 @@ "body-parser": "~1.18.2", "dotenv": "~2.0.0", "express": "~4.16.3", + "pusher": "~1.5.1", + "pusher-js": "~4.2.2", "querystring": "~0.2.0", "scrollmonitor": "~1.2.0", "vue": "~2.1.0", diff --git a/public/script.js b/public/script.js index a96bcad1..5a177150 100644 --- a/public/script.js +++ b/public/script.js @@ -1 +1,121 @@ -console.log('It works.'); +var PRICE = 9.99; +var LOAD_NUM = 10; + +var pusher = new Pusher('[PUSHER_KEY]', { + cluster: '[PUSHER_CLUSTER]', + encrypted: true +}); + +new Vue({ + el: '#app', + data: { + total: 0, + items: [], + results: [], + cart: [], + newSearch: 'anime', + lastSearch: '', + loading: false, + price: PRICE, + pusherUpdate: false + }, + mounted: function() { + this.onSubmit(); + var elem = document.getElementById('product-list-bottom'); + var watcher = scrollMonitor.create(elem); + var vue = this; + watcher.enterViewport(function() { + vue.appendItems(); + }); + var channel = pusher.subscribe('cart'); + channel.bind('update', function(data) { + vue.pusherUpdate = true; + vue.cart = data; + vue.total = 0; + for (var i = 0; i < vue.cart.length; i++) { + vue.total += PRICE * vue.cart[i].qty; + } + }); + }, + filters: { + currency: function(price) { + return '$'.concat(price.toFixed(2)); + } + }, + computed: { + noMoreItems: function() { + return this.results.length === this.items.length && this.results.length > 0; + } + }, + watch: { + cart: { + handler: function(val) { + if (!this.pusherUpdate) { + this.$http.post('/cart_update', val); + } else { + this.pusherUpdate = false; + } + }, + deep: true + } + }, + methods: { + appendItems: function() { + if (this.items.length < this.results.length) { + var append = this.results.slice(this.items.length, this.items.length + LOAD_NUM); + this.items = this.items.concat(append); + } + }, + onSubmit: function() { + if (this.newSearch.length) { + this.lastSearch = this.newSearch; + this.loading = true; + this.items = []; + this.results = []; + this.$http + .get('/search/'.concat(this.newSearch)) + .then(function(res) { + this.loading = false; + this.results = res.data; + this.appendItems(); + }) + ; + } + }, + addItem: function(index) { + var item = this.items[index]; + var found = false; + for (var i = 0; i < this.cart.length; i++) { + if (this.cart[i].id === item.id) { + this.cart[i].qty++; + found = true; + } + } + if (!found) { + this.cart = this.cart.concat({ + id: item.id, + title: item.title, + qty: 1, + price: PRICE + }); + } + this.total += PRICE; + }, + inc: function(item) { + item.qty++; + this.total += PRICE; + }, + dec: function(item) { + item.qty--; + this.total -= PRICE; + if (item.qty <= 0) { + for (var i = 0; i < this.cart.length; i++) { + if (this.cart[i].id === item.id) { + this.cart.splice(i, 1); + break; + } + } + } + } + } +});