almost finished new design on product page / reproduced bug with amount not updating

This commit is contained in:
Senad Uka
2015-05-13 16:32:53 +02:00
parent fe452d359f
commit 49dd10acbc
16 changed files with 158 additions and 234 deletions

View File

@@ -18,7 +18,7 @@
<div><%= section.delivery_destination.address %> </div>
<div><%= section.delivery_destination.place %> <%= Place.name_from_code(section.delivery_destination.place) %></div>
<div><%= section.delivery_destination.email %></div>
<div><strong><%= section.delivery_destination.phone %></strong></div>
<div><strong><%= section.delivery_destinati on.phone %></strong></div>
<% end %>

View File

@@ -11,166 +11,9 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150318174814) do
ActiveRecord::Schema.define(version: 0) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "carts", force: :cascade do |t|
t.integer "user_id"
t.boolean "ordered", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "anonymous_id_string"
t.integer "delivery_destination_id"
t.boolean "confirmed", default: false
t.boolean "packed", default: false
t.boolean "canceled_on_check", default: false
t.boolean "canceled_on_delivery", default: false
t.boolean "delivered", default: false
t.text "internal_note"
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.integer "section_id"
t.string "image_url"
t.integer "order"
end
create_table "delivery_destinations", force: :cascade do |t|
t.string "name"
t.string "address"
t.string "place"
t.string "postal_code"
t.string "phone"
t.string "email"
t.text "note"
t.boolean "email_verified"
t.boolean "phone_verified"
t.string "phone_verification_code"
t.string "email_verification_code"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "anonymous_id_string"
end
create_table "filter_criteria", force: :cascade do |t|
t.string "title"
t.string "field_name"
t.integer "type"
t.string "owner_type"
t.integer "owner_id"
end
create_table "filter_criteria_values", force: :cascade do |t|
t.string "filter_text"
t.string "filter_value"
t.integer "filter_criteria_id"
end
create_table "item_in_carts", force: :cascade do |t|
t.integer "cart_id"
t.integer "item_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "count"
t.decimal "price"
end
create_table "items", force: :cascade do |t|
t.string "name"
t.string "code", limit: 10
t.decimal "current_input_price", precision: 5, scale: 2
t.decimal "list_price", precision: 5, scale: 2
t.integer "unit_id"
t.decimal "units_in_pack", precision: 5, scale: 3
t.text "description"
t.integer "sub_category_id"
t.integer "stock"
t.boolean "on_display"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "tags"
t.json "traits"
t.decimal "weight", precision: 5, scale: 3
t.integer "special_offer_id"
t.integer "supplier_id"
end
create_table "media_types", force: :cascade do |t|
t.string "name"
end
create_table "multi_media_descriptions", force: :cascade do |t|
t.string "url"
t.integer "item_id"
t.integer "media_type_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "places", force: :cascade do |t|
t.string "postal_code"
t.decimal "delivery_price"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "sections", force: :cascade do |t|
t.string "name"
t.integer "order"
end
create_table "special_offers", force: :cascade do |t|
t.string "image_url"
t.boolean "start_page"
t.integer "section_id"
t.integer "category_id"
t.integer "sub_category_id"
t.integer "item_id"
t.boolean "thank_you_page"
t.boolean "search_result_page"
t.boolean "checkout_page"
t.date "beginning"
t.date "ending"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "sub_categories", force: :cascade do |t|
t.string "name"
t.integer "category_id"
t.integer "order"
end
create_table "suppliers", force: :cascade do |t|
t.string "name"
t.string "address"
t.string "postal_code"
t.string "town"
t.string "phone"
t.string "contact_person"
t.string "email"
t.text "note"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "units", force: :cascade do |t|
t.string "name"
t.string "short_name", limit: 4
t.string "description_suffix"
t.string "number_of_pieces_suffix"
end
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "password_digest"
end
end

4
back-office/import.log Normal file
View File

@@ -0,0 +1,4 @@
# Logfile created on 2015-05-13 07:02:12 +0200 by logger.rb/47272
I, [2015-05-13T07:02:12.557157 #35872] INFO -- : Item import starting at 2015-05-13 07:02:12 +0200
I, [2015-05-13T07:02:12.557196 #35872] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
I, [2015-05-13T07:02:25.997791 #35872] INFO -- : Import done

View File

@@ -0,0 +1,9 @@
# Logfile created on 2015-05-13 06:59:32 +0200 by logger.rb/47272
I, [2015-05-13T06:59:32.650998 #35530] INFO -- : Item import starting at 2015-05-13 06:59:32 +0200
I, [2015-05-13T06:59:32.651035 #35530] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
E, [2015-05-13T06:59:40.201578 #35530] ERROR -- : Could not import item on row number 608 (Dunjica), reason: Subcategory is missing!
I, [2015-05-13T06:59:45.758509 #35530] INFO -- : Rolling back because of errors
I, [2015-05-13T06:59:46.065723 #35530] INFO -- : Import done
I, [2015-05-13T07:00:24.402397 #35642] INFO -- : Item import starting at 2015-05-13 07:00:24 +0200
I, [2015-05-13T07:00:24.402456 #35642] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
I, [2015-05-13T07:00:37.829898 #35642] INFO -- : Import done

View File

@@ -200,11 +200,9 @@ ActiveRecord::Schema.define(version: 20150420044444) do
end
create_table "sub_categories", force: :cascade do |t|
t.string "name"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "order"
t.string "name"
t.integer "category_id"
t.integer "order"
end
create_table "suppliers", force: :cascade do |t|

View File

@@ -24,6 +24,14 @@ var CartActions = {
});
},
setItemCount: function(itemId, count) {
AppDispatcher.handleAction({
actionType: CartConstants.SET_ITEM_COUNT,
itemId: itemId,
count: count
});
},
dataLoaded: function() {
AppDispatcher.handleAction({
actionType: CartConstants.CART_DATA_LOADED

View File

@@ -1,6 +1,7 @@
var React = require('react');
var CartStore = require('../../stores/cartStore.js');
var CartActions = require('../../actions/cartActions.js');
var Globals = require('../../globals');
@@ -12,25 +13,23 @@ var AddToCart = React.createClass({
render: function() {
var itemCount = this.state.item.get('count');
var itemCount = this.state.count;
var moreThanZeroItems = (
var amountAndAddButton = (
<div className="row-fluid add-to-cart">
<div className="span12">
<div style={buttonHolderStyle}><button className="btn btn-default" onClick={this._onDecreaseClick}>-</button></div>
<div style={buttonHolderStyle}><button className="btn white_button" onClick={this._onDecreaseClick}>-</button></div>
<div style={buttonHolderStyle}> <div className="add-to-cart-count">{ itemCount }</div> </div>
<div style={buttonHolderStyle}><button className="btn btn-success" onClick={this._onIncreaseClick}>+ Dodaj</button></div>
<div style={buttonHolderStyle}><button className="btn white_button" onClick={this._onIncreaseClick}>+</button></div>
</div>
<div>
<div style={buttonHolderStyle}><button className="btn mybutton" onClick={this._addToCartClick}>Dodaj na popis za kupovinu</button></div>
</div>
</div>
);
var zeroItems = (<div className="row-fluid add-to-cart">
<div className="span12">
<div style={buttonHolderStyle}><button className="btn btn-success" onClick={this._onIncreaseClick}>Kupi</button></div>
</div>
</div> );
return (itemCount <= 0) ? zeroItems : moreThanZeroItems;
return amountAndAddButton;
},
// Add change listeners to stores
@@ -42,23 +41,38 @@ var AddToCart = React.createClass({
getInitialState: function() {
var itemInCart = CartStore.getStateFor(this.props.itemId);
return { item: itemInCart }
return {
item: itemInCart,
count: 0
}
},
_onChange: function () {
if (this.isMounted()) {
var item = CartStore.getStateFor(this.props.itemId);
this.setState({ item: item });
this.setState({ item: item, count: 0 });
}
},
_onIncreaseClick: function () {
CartActions.addItem(this.props.itemId);
//CartActions.addItem(this.props.itemId);
if (this.state.count < Globals.MaxNumberOfItemsToBeAdded ) {
this.state.count = this.state.count + 1;
this.setState(this.state);
}
},
_onDecreaseClick: function () {
CartActions.takeItemOut(this.props.itemId);
// CartActions.takeItemOut(this.props.itemId);
if (this.state.count > 0) {
this.state.count = this.state.count - 1;
this.setState(this.state);
}
},
_addToCartClick: function () {
CartActions.setItemCount(this.props.itemId, this.state.count);
},
componentWillUnmount: function () {

View File

@@ -16,22 +16,19 @@ var ItemWithDetailsPage = React.createClass({
return (
<div className="item-with-details row-fluid center">
<div className="col-md-5">
<Carousel images={this.state.images}
selected={this.state.currentImage}
onClickLeft={this.onClickLeft}
onClickRight={this.onClickRight}
onSelectImage={this.onSelectImage} />
<AddToCart itemId={this.state.item.get('id')} />
<div className="col-md-5 col-md-offset-2">
<img src={this.state.firstImage} width="100%" />
</div>
<div className="col-md-7">
<h3> {this.state.item.get('name')}</h3>
<div className="col-md-5">
<div className='item_brand_name'> {this.state.item.get('brand').name}</div>
<div className='item_name'> {this.state.item.get('name')}</div>
<div>
<div className='h4'> {this.state.item.get('brand').name}</div>
<div className='h4'> {this.state.item.get('list_price')} KM</div>
<div className='h5'>{this.state.item.get('pricePerUnit')}</div>
<div className='item_price'> {this.state.item.get('list_price')} KM</div>
<div>Količina</div>
<div> <AddToCart itemId={this.state.item.get('id')} /></div>
<div> {this.state.item.get('description')}</div>
</div>

View File

@@ -4,11 +4,11 @@ var keyMirror = require('react/lib/keyMirror');
module.exports = keyMirror({
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 ,
CART_DATA_LOADED: null,
SAVE_CART_STATE_FOR_ITEM: null,
CHANGE_DELIVERY_DESTINATION_PROPERTY: null,
CONFIRM_DELIVERY: null
CONFIRM_DELIVERY: null,
SET_ITEM_COUNT: null,
REMOVE_ITEM: null
});

View File

@@ -32,3 +32,22 @@
text-align: center;
padding-right: 5px;
}
.item_name {
font-size: 16px;
}
.item_brand_name {
font-size: 24px;
text-transform: uppercase;
}
.item_price {
font-size: 36px;
padding-top: 36px;
padding-bottom: 36px;
}

View File

@@ -464,3 +464,16 @@ text-decoration: none;
.error-message {
color: red;
}
.white_button{
background-color: #f9f9f9;
width: 40px;
height: 40px;
padding-bottom: 7px;
display: block;
border-radius: 1px;
margin-top: 8px;
border: solid #cccccc 1px;
color: #4d4d4d !important;
font-size: 16px;
}

View File

@@ -5,5 +5,6 @@ module.exports = {
FormatCurrency: function(amount_s) {
var amount = parseFloat(amount_s);
return ( amount.toFixed(2) + " KM" )
}
},
MaxNumberOfItemsToBeAdded: 1000
};

View File

@@ -101,6 +101,19 @@ var takeItemOut = function(itemId) {
saveCartStateForItem(itemId);
};
var setItemCount = function(itemId, count) {
var state = states[itemId] || new ItemInCart({
item_id: itemId,
count: 0
})
console.log("Old state", state.get('count'));
state.set('count', state.get('count') + count);
console.log("New state", state.get('count'));
states[itemId] = state;
saveCartStateForItem(itemId);
}
var changeDeliveryDestinationProperty = function(property, value) {
_deliveryDestination.set(property, value);
@@ -274,6 +287,9 @@ AppDispatcher.register(function(payload) {
case CartConstants.CONFIRM_DELIVERY:
saveDeliveryDestination();
break;
case CartConstants.SET_ITEM_COUNT:
setItemCount(action.itemId, action.count);
break;
default:
return true;
}

View File

@@ -76,12 +76,13 @@ var ItemWithDetailsStore = _.extend({}, EventEmitter.prototype, {
getState: function() {
var firstImage = _images[0] || "https://res.cloudinary.com/lfvt7ps2n/image/upload/c_fit,h_172,w_226/v1421732950/http_www.asms.ru_bitrix_templates_main_images_nophoto_irnofq.png";
return {
item: _itemWithDetails,
images: _images,
currentImage: _currentImage,
count: _count
count: _count,
firstImage: firstImage
}
},

View File

@@ -53,33 +53,34 @@ var fetchItemWithDetails = function() {
}
var fetchItemsByCategory = function(categoryId, offset, limit, query) {
//var items = _itemsByCategory;
var items = new ItemCollection();
items.clearFilter();
items.setClassificationType(2);
items.setClassificationId(categoryId);
items.setLimit(limit);
items.setOffset(offset);
//var items = _itemsByCategory;
var items = new ItemCollection();
items.clearFilter();
items.setClassificationType(2);
items.setClassificationId(categoryId);
items.setLimit(limit);
items.setOffset(offset);
for(var key in query) {
if (query.hasOwnProperty(key) && key != 'limit' && key !='offset') {
items.addFilter(key, query[key]);
for (var key in query) {
if (query.hasOwnProperty(key) && key != 'limit' && key != 'offset') {
items.addFilter(key, query[key]);
}
}
}
items.fetch({
success: function(collection, response, options) {
var total = options.xhr.getResponseHeader('x-total-count');
items.setTotalCount(total);
items.fetch({
success: function(collection, response, options) {
var total = options.xhr.getResponseHeader('x-total-count');
items.setTotalCount(total);
ItemStore.emitChange();
}});
ItemStore.emitChange();
}
});
_itemsByCategory = items;
_itemsByCategory = items;
};
var fetchBestSellingItemsForSection = function(sectionId) {
console.log('getting section', sectionId);
console.log('getting section', sectionId);
var items = _bestSellingForSection;
items.setClassificationType(1);
items.setClassificationId(sectionId);
@@ -87,15 +88,15 @@ var fetchBestSellingItemsForSection = function(sectionId) {
items.setOffset(0);
items.fetch({
success: function() {
ItemStore.emitChange();
}
success: function() {
ItemStore.emitChange();
}
});
};
var fetchBestSellingItemsForGroup = function(groupId) {
console.log('getting group', groupId);
console.log('getting group', groupId);
var items = _bestSellingForGroup;
items.setClassificationType(4);
items.setClassificationId(groupId);
@@ -103,9 +104,9 @@ var fetchBestSellingItemsForGroup = function(groupId) {
items.setOffset(0);
items.fetch({
success: function() {
ItemStore.emitChange();
}
success: function() {
ItemStore.emitChange();
}
});
};
@@ -113,19 +114,19 @@ var fetchBestSellingItemsForGroup = function(groupId) {
// Extend ItemStore with EventEmitter to add eventing capabilities
var ItemStore = _.extend({}, EventEmitter.prototype, {
getItemsForCategory: function() {
return _itemsByCategory;
},
getItemsForCategory: function() {
return _itemsByCategory;
},
getBestSellingForSection: function() {
return _bestSellingForSection;
return _bestSellingForSection;
},
// item with details
getLoadedItemWithDetails: function() {
return _itemWithDetails;
},
getItemsForGroup: function () {
getItemsForGroup: function() {
return _bestSellingForGroup;
},
@@ -190,4 +191,4 @@ AppDispatcher.register(function(payload) {
});
module.exports = ItemStore;
module.exports = ItemStore;

View File

@@ -9,21 +9,21 @@
"author": "",
"license": "BSD-2-Clause",
"devDependencies": {
"Backbone.Mutators": "~0.4.4",
"browserify": "~8.1.0",
"events": "^1.0.2",
"flux": "^2.0.1",
"grunt": "~0.4.5",
"grunt": "^0.4.5",
"grunt-browserify": "~3.2.1",
"grunt-cli": "~0.1.13",
"grunt-config": "~0.2.2",
"grunt-contrib-concat": "~0.5.0",
"grunt-contrib-connect": "~0.9.0",
"grunt-contrib-uglify": "~0.7.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-replace": "~0.8.0",
"reactify": "~0.17.1",
"underscore": "^1.7.0",
"Backbone.Mutators": "~0.4.4",
"grunt-config": "~0.2.2",
"grunt-replace": "~0.8.0"
"underscore": "^1.7.0"
},
"dependencies": {
"react": "~0.12.2",