cart state for item in details page finnaly shows (arrggh worst kind of bugs)

This commit is contained in:
Senad Uka
2015-02-08 08:29:24 +01:00
parent 7770e59b81
commit 113b70e8fa
11 changed files with 139 additions and 37 deletions

View File

@@ -13,12 +13,18 @@ before do
content_type :json content_type :json
# TODO: before running to production change this so that only specific # TODO: before running to production change this so that only specific
# domain is allowed # domain is allowed
headers 'Access-Control-Allow-Origin' => '*', headers 'Access-Control-Allow-Origin' => 'http://localhost:3001',
'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST'] '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 request.body.rewind
json_string = request.body.read json_string = request.body.read
@json_params = JSON.parse json_string if json_string.length > 1 @json_params = JSON.parse json_string if json_string.length > 1
if request.request_method == 'OPTIONS'
halt 200
end
end end
@@ -28,5 +34,3 @@ helpers Sinatra::Cookies
Dir[File.dirname(__FILE__) + '/controllers/*.rb'].each {|file| require file } Dir[File.dirname(__FILE__) + '/controllers/*.rb'].each {|file| require file }

View File

@@ -21,9 +21,13 @@ get '/cart/item' do
Cart.find_or_create(anonymous_id, -1).item_in_carts.to_json Cart.find_or_create(anonymous_id, -1).item_in_carts.to_json
end end
post '/cart/item' do
update_cart_item = ->() {
cart_id = Cart.find_or_create(anonymous_id, -1).id cart_id = Cart.find_or_create(anonymous_id, -1).id
item_id = @json_params["item_id"] item_id = @json_params["item_id"].to_i
count = @json_params["count"] count = @json_params["count"].to_i
ItemInCart.update_state(cart_id, item_id, count).to_json ItemInCart.update_state(cart_id, item_id, count).to_json
end }
put '/cart/item', &update_cart_item
post '/cart/item', &update_cart_item

View File

@@ -1,5 +1,6 @@
class Cart < ActiveRecord::Base class Cart < ActiveRecord::Base
has_many :item_in_carts, -> { order "created_at" } has_many :item_in_carts, -> { order "created_at" }
def self.find_or_create(anonymous_id, user_id) def self.find_or_create(anonymous_id, user_id)
cart = Cart.where(user_id: user_id).where(ordered: false).first cart = Cart.where(user_id: user_id).where(ordered: false).first
cart ||= Cart.where(anonymous_id_string: anonymous_id).where(ordered: false).first cart ||= Cart.where(anonymous_id_string: anonymous_id).where(ordered: false).first

View File

@@ -6,11 +6,10 @@ var CartActions = {
load: function() { load: function() {
AppDispatcher.handleAction({ AppDispatcher.handleAction({
actionType: CartConstants.LOAD actionType: CartConstants.LOAD_CART_CONTENTS
}); });
}, },
addItem: function(itemId) { addItem: function(itemId) {
AppDispatcher.handleAction({ AppDispatcher.handleAction({
actionType: CartConstants.ADD_ITEM, actionType: CartConstants.ADD_ITEM,
@@ -23,6 +22,12 @@ var CartActions = {
actionType: CartConstants.TAKE_ITEM_OUT, actionType: CartConstants.TAKE_ITEM_OUT,
itemId: itemId itemId: itemId
}); });
},
dataLoaded: function() {
AppDispatcher.handleAction({
actionType: CartConstants.CART_DATA_LOADED
});
} }
}; };

View File

@@ -11,10 +11,11 @@ var countStyle = {
var AddToCart = React.createClass({ var AddToCart = React.createClass({
render: function() { render: function() {
return ( return (
<div className="row-fluid add-to-cart"> <div className="row-fluid add-to-cart">
<div className="col-xs-offset-1 col-xs-1"><button className="btn btn-success" onClick={this._onIncreaseClick}>+</button></div> <div className="col-xs-offset-1 col-xs-1"><button className="btn btn-success" onClick={this._onIncreaseClick}>+</button></div>
<div className="col-xs-2"><button className="btn" style={countStyle} > { this.state.count } </button></div> <div className="col-xs-2"><button className="btn" style={countStyle} > { this.state.item.get('count') } </button></div>
<div className="col-xs-1"><button className="btn btn-success" onClick={this._onDecreaseClick}>-</button></div> <div className="col-xs-1"><button className="btn btn-success" onClick={this._onDecreaseClick}>-</button></div>
<div className="col-xs-7"><button className="btn btn-warning">U korpu</button></div> <div className="col-xs-7"><button className="btn btn-warning">U korpu</button></div>
</div> </div>
@@ -23,19 +24,23 @@ var AddToCart = React.createClass({
// Add change listeners to stores // Add change listeners to stores
componentDidMount: function() { componentDidMount: function() {
CartActions.load();
CartStore.addChangeListener(this._onChange); CartStore.addChangeListener(this._onChange);
CartActions.load();
}, },
getInitialState: function() { getInitialState: function() {
return CartStore.getStateFor(this.props.itemId)
var itemInCart = CartStore.getStateFor(this.props.itemId);
return { item: itemInCart }
}, },
_onChange: function () { _onChange: function () {
if (this.isMounted()) { if (this.isMounted()) {
this.setState(CartStore.getStateFor(this.props.itemId)); var item = CartStore.getStateFor(this.props.itemId);
this.setState({ item: item });
} }
}, },

View File

@@ -22,7 +22,7 @@ var ItemWithDetailsPage = React.createClass({
onClickLeft={this.onClickLeft} onClickLeft={this.onClickLeft}
onClickRight={this.onClickRight} onClickRight={this.onClickRight}
onSelectImage={this.onSelectImage} /> onSelectImage={this.onSelectImage} />
<AddToCart itemId={this.state.item.id} /> <AddToCart itemId={this.state.item.get('id')} />
</div> </div>

View File

@@ -2,9 +2,10 @@ var keyMirror = require('react/lib/keyMirror');
// Define action constants // Define action constants
module.exports = keyMirror({ module.exports = keyMirror({
LOAD: null, LOAD_CART_CONTENTS: null,
ADD_ITEM: null, ADD_ITEM: null,
// because REMOVE_ITEM could be used to completely remove item // because REMOVE_ITEM could be used to completely remove item
// and not just decrease count by 1 // and not just decrease count by 1
TAKE_ITEM_OUT: null TAKE_ITEM_OUT: null ,
CART_DATA_LOADED: null
}); });

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,30 +1,60 @@
var AppDispatcher = require('../dispatcher/appDispatcher'); var AppDispatcher = require('../dispatcher/appDispatcher');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var CartConstants = require('../constants/cartConstants'); var CartConstants = require('../constants/cartConstants');
var CartActions = require('../actions/cartActions');
var ItemInCart = require('../models/itemInCart');
var ItemInCartCollection = require('../models/itemInCartCollection');
var _ = require('underscore'); var _ = require('underscore');
var states = { var states = {}
}
var _itemsInCart = new ItemInCartCollection();
var loadCart = function() { 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) { var addItem = function(itemId) {
// TODO: push state to server side
var state = states[itemId] || { count: 0 }; var state = states[itemId] || new ItemInCart({
state.count++; item_id: itemId,
count: 0
})
state.set('count', state.get('count') + 1);
states[itemId] = state; states[itemId] = state;
state.save({
success: function () {
CartActions.dataLoaded();
}
});
}; };
var takeItemOut = function(itemId) { var takeItemOut = function(itemId) {
// TODO: push state to server side
var state = states[itemId] || { count: 0 }; var state = states[itemId] || new ItemInCart({
if (state.count > 0) { item_id: itemId,
state.count--; count: 0
})
if (state.get('count') > 0) {
state.set('count', state.get('count') - 1);
} }
states[itemId] = state; states[itemId] = state;
state.save({
success: function () {
CartActions.dataLoaded();
}
});
}; };
@@ -34,14 +64,18 @@ var takeItemOut = function(itemId) {
var CartStore = _.extend({}, EventEmitter.prototype, { var CartStore = _.extend({}, EventEmitter.prototype, {
getStateFor: function(itemId) { getStateFor: function(itemId) {
// TODO: get from server side ?
var state = states[itemId] || { count: 0 } // TODO: get from server side ?
return state var state = states[itemId] || new ItemInCart({
item_id: itemId,
count: 0
})
return state
}, },
// Emit Change event // Emit Change event
emitChange: function() { emitChange: function() {
console.log("Emitting change!"); console.log("Emitting cart change!");
this.emit('change'); this.emit('change');
}, },
@@ -65,7 +99,7 @@ AppDispatcher.register(function(payload) {
switch (action.actionType) { switch (action.actionType) {
case CartConstants.LOAD: case CartConstants.LOAD_CART_CONTENTS:
loadCart(); loadCart();
break; break;
@@ -76,6 +110,9 @@ AppDispatcher.register(function(payload) {
case CartConstants.TAKE_ITEM_OUT: case CartConstants.TAKE_ITEM_OUT:
takeItemOut(action.itemId); takeItemOut(action.itemId);
break; break;
case CartConstants.CART_DATA_LOADED:
// just emit change
break;
default: default:
return true; return true;

View File

@@ -29,9 +29,9 @@ var fetchItemWithDetails = function() {
var item = new ItemWithDetails({ var item = new ItemWithDetails({
id: id id: id
}); });
_itemWithDetails = item;
item.fetch({ item.fetch({
success: function() { success: function() {
_itemWithDetails = item;
_images = (_itemWithDetails.get("multi_media_descriptions") || []).map(function(mmd) { _images = (_itemWithDetails.get("multi_media_descriptions") || []).map(function(mmd) {
return mmd.url; return mmd.url;
}); });