diff --git a/back-office/app/views/reports/orders_to_confirm.html.erb b/back-office/app/views/reports/orders_to_confirm.html.erb index b9b599d..ef65fca 100644 --- a/back-office/app/views/reports/orders_to_confirm.html.erb +++ b/back-office/app/views/reports/orders_to_confirm.html.erb @@ -18,7 +18,7 @@
<%= section.delivery_destination.address %>
<%= section.delivery_destination.place %> <%= Place.name_from_code(section.delivery_destination.place) %>
<%= section.delivery_destination.email %>
-
<%= section.delivery_destination.phone %>
+
<%= section.delivery_destinati on.phone %>
<% end %> diff --git a/back-office/db/schema.rb b/back-office/db/schema.rb index 8c20fd6..ea89ed5 100644 --- a/back-office/db/schema.rb +++ b/back-office/db/schema.rb @@ -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 diff --git a/back-office/import.log b/back-office/import.log new file mode 100644 index 0000000..1b817d4 --- /dev/null +++ b/back-office/import.log @@ -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 diff --git a/back-office/import_validate.log b/back-office/import_validate.log new file mode 100644 index 0000000..114ebc9 --- /dev/null +++ b/back-office/import_validate.log @@ -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 diff --git a/front-api/db/schema.rb b/front-api/db/schema.rb index 9443ceb..6290743 100644 --- a/front-api/db/schema.rb +++ b/front-api/db/schema.rb @@ -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| diff --git a/front-ui/app/actions/cartActions.js b/front-ui/app/actions/cartActions.js index c1a7c8c..4da0adc 100644 --- a/front-ui/app/actions/cartActions.js +++ b/front-ui/app/actions/cartActions.js @@ -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 diff --git a/front-ui/app/components/cart/addToCart.js b/front-ui/app/components/cart/addToCart.js index b7d5e8a..62c324a 100644 --- a/front-ui/app/components/cart/addToCart.js +++ b/front-ui/app/components/cart/addToCart.js @@ -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 = (
-
+
{ itemCount }
-
+
+
+
+
); - var zeroItems = (
-
-
-
-
); - 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 () { diff --git a/front-ui/app/components/items/itemWithDetailsPage.js b/front-ui/app/components/items/itemWithDetailsPage.js index 63ef7f1..8f5f6f0 100644 --- a/front-ui/app/components/items/itemWithDetailsPage.js +++ b/front-ui/app/components/items/itemWithDetailsPage.js @@ -16,22 +16,19 @@ var ItemWithDetailsPage = React.createClass({ return (
-
- - - +
+
-
-

{this.state.item.get('name')}

+
+
{this.state.item.get('brand').name}
+
{this.state.item.get('name')}
-
{this.state.item.get('brand').name}
-
{this.state.item.get('list_price')} KM
-
{this.state.item.get('pricePerUnit')}
+
{this.state.item.get('list_price')} KM
+ +
Količina
+ +
{this.state.item.get('description')}
diff --git a/front-ui/app/constants/cartConstants.js b/front-ui/app/constants/cartConstants.js index 4a919fa..4a62ba0 100644 --- a/front-ui/app/constants/cartConstants.js +++ b/front-ui/app/constants/cartConstants.js @@ -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 }); diff --git a/front-ui/app/css/items.css b/front-ui/app/css/items.css index 4ddfaf5..1b88514 100644 --- a/front-ui/app/css/items.css +++ b/front-ui/app/css/items.css @@ -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; + + +} \ No newline at end of file diff --git a/front-ui/app/css/main.css b/front-ui/app/css/main.css index 238a4df..cd58290 100644 --- a/front-ui/app/css/main.css +++ b/front-ui/app/css/main.css @@ -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; +} diff --git a/front-ui/app/globals.js b/front-ui/app/globals.js index 11deca3..a062ce7 100644 --- a/front-ui/app/globals.js +++ b/front-ui/app/globals.js @@ -5,5 +5,6 @@ module.exports = { FormatCurrency: function(amount_s) { var amount = parseFloat(amount_s); return ( amount.toFixed(2) + " KM" ) - } + }, + MaxNumberOfItemsToBeAdded: 1000 }; diff --git a/front-ui/app/stores/cartStore.js b/front-ui/app/stores/cartStore.js index 7659d05..7a387d8 100644 --- a/front-ui/app/stores/cartStore.js +++ b/front-ui/app/stores/cartStore.js @@ -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; } diff --git a/front-ui/app/stores/itemDetailsStore.js b/front-ui/app/stores/itemDetailsStore.js index 753e238..0c48b93 100644 --- a/front-ui/app/stores/itemDetailsStore.js +++ b/front-ui/app/stores/itemDetailsStore.js @@ -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 } }, diff --git a/front-ui/app/stores/itemStore.js b/front-ui/app/stores/itemStore.js index 1a4af6f..80ee48c 100644 --- a/front-ui/app/stores/itemStore.js +++ b/front-ui/app/stores/itemStore.js @@ -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; \ No newline at end of file diff --git a/front-ui/package.json b/front-ui/package.json index d214bdd..39762d5 100644 --- a/front-ui/package.json +++ b/front-ui/package.json @@ -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",