diff --git a/front-api/app.rb b/front-api/app.rb index 6a28494..696a71b 100644 --- a/front-api/app.rb +++ b/front-api/app.rb @@ -13,12 +13,18 @@ before do content_type :json # TODO: before running to production change this so that only specific # domain is allowed - headers 'Access-Control-Allow-Origin' => '*', - 'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST'] - + headers 'Access-Control-Allow-Origin' => 'http://localhost:3001', + 'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST','PUT'], + 'Access-Control-Allow-Headers' => 'Origin, X-Requested-With, Content-Type, Accept', + 'Access-Control-Allow-Credentials' => 'true' + request.body.rewind - json_string = request.body.read + json_string = request.body.read @json_params = JSON.parse json_string if json_string.length > 1 + + if request.request_method == 'OPTIONS' + halt 200 + end end @@ -28,5 +34,3 @@ helpers Sinatra::Cookies Dir[File.dirname(__FILE__) + '/controllers/*.rb'].each {|file| require file } - - diff --git a/front-api/controllers/cart.rb b/front-api/controllers/cart.rb index 9fd0b05..fd33f19 100644 --- a/front-api/controllers/cart.rb +++ b/front-api/controllers/cart.rb @@ -21,9 +21,13 @@ get '/cart/item' do Cart.find_or_create(anonymous_id, -1).item_in_carts.to_json end -post '/cart/item' do + +update_cart_item = ->() { cart_id = Cart.find_or_create(anonymous_id, -1).id - item_id = @json_params["item_id"] - count = @json_params["count"] + item_id = @json_params["item_id"].to_i + count = @json_params["count"].to_i ItemInCart.update_state(cart_id, item_id, count).to_json -end +} +put '/cart/item', &update_cart_item +post '/cart/item', &update_cart_item + diff --git a/front-api/models/cart.rb b/front-api/models/cart.rb index 942ca49..dc92954 100644 --- a/front-api/models/cart.rb +++ b/front-api/models/cart.rb @@ -1,5 +1,6 @@ class Cart < ActiveRecord::Base has_many :item_in_carts, -> { order "created_at" } + def self.find_or_create(anonymous_id, user_id) cart = Cart.where(user_id: user_id).where(ordered: false).first cart ||= Cart.where(anonymous_id_string: anonymous_id).where(ordered: false).first diff --git a/front-ui/app/actions/cartActions.js b/front-ui/app/actions/cartActions.js index cfc8b44..7b6e62a 100644 --- a/front-ui/app/actions/cartActions.js +++ b/front-ui/app/actions/cartActions.js @@ -6,11 +6,10 @@ var CartActions = { load: function() { AppDispatcher.handleAction({ - actionType: CartConstants.LOAD + actionType: CartConstants.LOAD_CART_CONTENTS }); }, - addItem: function(itemId) { AppDispatcher.handleAction({ actionType: CartConstants.ADD_ITEM, @@ -23,6 +22,12 @@ var CartActions = { actionType: CartConstants.TAKE_ITEM_OUT, itemId: itemId }); + }, + + dataLoaded: function() { + AppDispatcher.handleAction({ + actionType: CartConstants.CART_DATA_LOADED + }); } }; diff --git a/front-ui/app/components/cart/addToCart.js b/front-ui/app/components/cart/addToCart.js index 0ab6f4c..6cd2c83 100644 --- a/front-ui/app/components/cart/addToCart.js +++ b/front-ui/app/components/cart/addToCart.js @@ -11,31 +11,36 @@ var countStyle = { var AddToCart = React.createClass({ render: function() { + return (
-
+
-
+ ); }, // Add change listeners to stores componentDidMount: function() { - CartActions.load(); CartStore.addChangeListener(this._onChange); + + CartActions.load(); }, getInitialState: function() { - return CartStore.getStateFor(this.props.itemId) + + var itemInCart = CartStore.getStateFor(this.props.itemId); + return { item: itemInCart } }, _onChange: function () { if (this.isMounted()) { - this.setState(CartStore.getStateFor(this.props.itemId)); + var item = CartStore.getStateFor(this.props.itemId); + this.setState({ item: item }); } }, diff --git a/front-ui/app/components/items/itemWithDetailsPage.js b/front-ui/app/components/items/itemWithDetailsPage.js index 2d0098d..3361fc5 100644 --- a/front-ui/app/components/items/itemWithDetailsPage.js +++ b/front-ui/app/components/items/itemWithDetailsPage.js @@ -22,7 +22,7 @@ var ItemWithDetailsPage = React.createClass({ onClickLeft={this.onClickLeft} onClickRight={this.onClickRight} onSelectImage={this.onSelectImage} /> - + diff --git a/front-ui/app/constants/cartConstants.js b/front-ui/app/constants/cartConstants.js index 5b2a25f..ec14409 100644 --- a/front-ui/app/constants/cartConstants.js +++ b/front-ui/app/constants/cartConstants.js @@ -2,9 +2,10 @@ var keyMirror = require('react/lib/keyMirror'); // Define action constants module.exports = keyMirror({ - LOAD: null, + LOAD_CART_CONTENTS: null, ADD_ITEM: null, // because REMOVE_ITEM could be used to completely remove item // and not just decrease count by 1 - TAKE_ITEM_OUT: null + TAKE_ITEM_OUT: null , + CART_DATA_LOADED: null }); diff --git a/front-ui/app/models/itemInCart.js b/front-ui/app/models/itemInCart.js new file mode 100644 index 0000000..8dc2518 --- /dev/null +++ b/front-ui/app/models/itemInCart.js @@ -0,0 +1,22 @@ +var Backbone = require('backbone'); +var Globals = require('../globals'); + +var ItemInCart = Backbone.Model.extend({ + + initialize: function() { + $.ajaxPrefilter( + function(options, originalOptions, jqXHR) { + options.xhrFields = { + withCredentials: true + } + } + ); + }, + + url: Globals.ApiUrl + '/cart/item', + defaults: { + count: 0 + } +}); + +module.exports = ItemInCart; \ No newline at end of file diff --git a/front-ui/app/models/itemInCartCollection.js b/front-ui/app/models/itemInCartCollection.js new file mode 100644 index 0000000..7461312 --- /dev/null +++ b/front-ui/app/models/itemInCartCollection.js @@ -0,0 +1,23 @@ +var Backbone = require('backbone'), + ItemInCart = require('./itemInCart'), + Globals = require('../globals'); + +var ItemInCartCollection = Backbone.Collection.extend({ + + initialize: function() { + $.ajaxPrefilter( + function(options, originalOptions, jqXHR) { + options.xhrFields = { + withCredentials: true + } + } + ); + }, + + model: ItemInCart, + url: Globals.ApiUrl + '/cart/item' + + +}); + +module.exports = ItemInCartCollection; \ No newline at end of file diff --git a/front-ui/app/stores/cartStore.js b/front-ui/app/stores/cartStore.js index bbc0d04..072baa6 100644 --- a/front-ui/app/stores/cartStore.js +++ b/front-ui/app/stores/cartStore.js @@ -1,30 +1,60 @@ var AppDispatcher = require('../dispatcher/appDispatcher'); var EventEmitter = require('events').EventEmitter; var CartConstants = require('../constants/cartConstants'); +var CartActions = require('../actions/cartActions'); +var ItemInCart = require('../models/itemInCart'); +var ItemInCartCollection = require('../models/itemInCartCollection'); var _ = require('underscore'); -var states = { -} +var states = {} + +var _itemsInCart = new ItemInCartCollection(); var loadCart = function() { - + _itemsInCart.fetch({ + success: function() { + states = {} + for (var i = 0; i < _itemsInCart.models.length; i++) { + var itemInCart = _itemsInCart.models[i]; + states[itemInCart.get('item_id')] = itemInCart; + } + CartActions.dataLoaded(); + } + }) }; var addItem = function(itemId) { - // TODO: push state to server side - var state = states[itemId] || { count: 0 }; - state.count++; + + var state = states[itemId] || new ItemInCart({ + item_id: itemId, + count: 0 + }) + state.set('count', state.get('count') + 1); states[itemId] = state; + state.save({ + success: function () { + CartActions.dataLoaded(); + } + }); + }; var takeItemOut = function(itemId) { - // TODO: push state to server side - var state = states[itemId] || { count: 0 }; - if (state.count > 0) { - state.count--; + + var state = states[itemId] || new ItemInCart({ + item_id: itemId, + count: 0 + }) + if (state.get('count') > 0) { + state.set('count', state.get('count') - 1); } states[itemId] = state; + state.save({ + success: function () { + CartActions.dataLoaded(); + } + }); }; @@ -34,14 +64,18 @@ var takeItemOut = function(itemId) { var CartStore = _.extend({}, EventEmitter.prototype, { getStateFor: function(itemId) { - // TODO: get from server side ? - var state = states[itemId] || { count: 0 } - return state + + // TODO: get from server side ? + var state = states[itemId] || new ItemInCart({ + item_id: itemId, + count: 0 + }) + return state }, // Emit Change event emitChange: function() { - console.log("Emitting change!"); + console.log("Emitting cart change!"); this.emit('change'); }, @@ -65,7 +99,7 @@ AppDispatcher.register(function(payload) { switch (action.actionType) { - case CartConstants.LOAD: + case CartConstants.LOAD_CART_CONTENTS: loadCart(); break; @@ -76,6 +110,9 @@ AppDispatcher.register(function(payload) { case CartConstants.TAKE_ITEM_OUT: takeItemOut(action.itemId); break; + case CartConstants.CART_DATA_LOADED: + // just emit change + break; default: return true; @@ -87,4 +124,4 @@ AppDispatcher.register(function(payload) { }); -module.exports = CartStore; +module.exports = CartStore; \ No newline at end of file diff --git a/front-ui/app/stores/itemDetailsStore.js b/front-ui/app/stores/itemDetailsStore.js index f377208..029bd59 100644 --- a/front-ui/app/stores/itemDetailsStore.js +++ b/front-ui/app/stores/itemDetailsStore.js @@ -29,9 +29,9 @@ var fetchItemWithDetails = function() { var item = new ItemWithDetails({ id: id }); + _itemWithDetails = item; item.fetch({ success: function() { - _itemWithDetails = item; _images = (_itemWithDetails.get("multi_media_descriptions") || []).map(function(mmd) { return mmd.url; });