From 01c4882759f42c2d4a227545acb9f6e3f329a98e Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 18 Jun 2020 10:36:10 +1000 Subject: [PATCH] Replace bulk buy inputs with add-remove-buttons --- .../directives/shop_variant.js.coffee | 32 +++++++-- .../templates/bulk_buy_modal.html.haml | 34 ++++++++++ .../shop_variant_with_group_buy.html.haml | 41 +++++------- .../stylesheets/darkswarm/_shop-inputs.scss | 67 +++++++------------ .../consumer/shopping/shopping_spec.rb | 26 ++++--- spec/support/request/shop_workflow.rb | 29 ++++---- spec/support/request/ui_component_helper.rb | 4 ++ 7 files changed, 140 insertions(+), 93 deletions(-) create mode 100644 app/assets/javascripts/templates/bulk_buy_modal.html.haml diff --git a/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee b/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee index 55c72abfe1..97caf2a8b5 100644 --- a/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/shop_variant.js.coffee @@ -4,7 +4,7 @@ Darkswarm.directive "shopVariant", -> templateUrl: 'shop_variant.html' scope: variant: '=' - controller: ($scope, Cart) -> + controller: ($scope, $modal, Cart) -> $scope.$watchGroup [ 'variant.line_item.quantity', 'variant.line_item.max_quantity' @@ -13,9 +13,33 @@ Darkswarm.directive "shopVariant", -> Cart.adjust($scope.variant.line_item) $scope.add = (quantity) -> - $scope.variant.line_item.quantity += quantity + item = $scope.variant.line_item + item.quantity += quantity + if $scope.variant.product.group_buy + if item.quantity < 1 || item.max_quantity < item.quantity + item.max_quantity = item.quantity + + $scope.addMax = (quantity) -> + item = $scope.variant.line_item + item.max_quantity += quantity + if item.max_quantity < item.quantity + item.quantity = item.max_quantity $scope.canAdd = (quantity) -> + wantedQuantity = $scope.variant.line_item.quantity + quantity + $scope.quantityValid(wantedQuantity) + + $scope.canAddMax = (quantity) -> variant = $scope.variant - wantedQuantity = variant.line_item.quantity + quantity - variant.on_demand || wantedQuantity <= variant.on_hand + wantedQuantity = variant.line_item.max_quantity + quantity + $scope.quantityValid(wantedQuantity) && variant.line_item.quantity > 0 + + $scope.quantityValid = (quantity) -> + variant = $scope.variant + minimum = 0 + maximum = variant.on_demand && Infinity || variant.on_hand + quantity >= minimum && quantity <= maximum + + $scope.addBulk = (quantity) -> + $scope.add(quantity) + $modal.open(templateUrl: "bulk_buy_modal.html", scope: $scope) diff --git a/app/assets/javascripts/templates/bulk_buy_modal.html.haml b/app/assets/javascripts/templates/bulk_buy_modal.html.haml new file mode 100644 index 0000000000..1e03b459b1 --- /dev/null +++ b/app/assets/javascripts/templates/bulk_buy_modal.html.haml @@ -0,0 +1,34 @@ +.row + .columns.small-12 + %h3{"ng-bind" => "::variant.extended_name"} + +.row.variant-bulk-buy-price-summary + .columns.small-6 + .variant-unit {{ ::variant.unit_to_display }} + .columns.small-6 + {{ variant.line_item.total_price | localizeCurrency }} + +.row + .columns.small-6 + .variant-bulk-buy-quantity-label + Min quantity + %div + %button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(-1)", disabled: "!canAdd(-1)"}}> + {{ "js.shop_variant_no_group_buy.decrement" | t }} + %span.bulk-buy.variant-quantity> + {{ variant.line_item.quantity }} + %button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(1)", disabled: "!canAdd(1)"}} + {{ "js.shop_variant_no_group_buy.increment" | t }} + .columns.small-6 + .variant-bulk-buy-quantity-label + Max quantity + %div + %button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(-1)", disabled: "!canAddMax(-1)"}}> + {{ "js.shop_variant_no_group_buy.decrement" | t }} + %span.bulk-buy.variant-quantity> + {{ variant.line_item.max_quantity }} + %button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(1)", disabled: "!canAddMax(1)"}} + {{ "js.shop_variant_no_group_buy.increment" | t }} + + +%ng-include{src: "'partials/close.html'"} diff --git a/app/assets/javascripts/templates/partials/shop_variant_with_group_buy.html.haml b/app/assets/javascripts/templates/partials/shop_variant_with_group_buy.html.haml index c0cc46ac13..aa34349ea2 100644 --- a/app/assets/javascripts/templates/partials/shop_variant_with_group_buy.html.haml +++ b/app/assets/javascripts/templates/partials/shop_variant_with_group_buy.html.haml @@ -1,28 +1,17 @@ .small-5.medium-3.large-3.columns.text-right{"ng-if" => "::variant.product.group_buy"} - %span.bulk-input-container - %span.bulk-input - %input.bulk.first{type: :number, - value: nil, - integer: true, - min: 0, - "ng-model" => "variant.line_item.quantity", - placeholder: "{{::'shop_variant_quantity_min' | t}}", - "ofn-disable-scroll" => true, - "ng-debounce" => "500", - onwheel: "this.blur()", - "ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}", - name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"} - %span.bulk-input - %input.bulk.second{type: :number, - "ng-disabled" => "!variant.line_item.quantity", - integer: true, - min: 0, - "ng-model" => "variant.line_item.max_quantity", - placeholder: "{{::'shop_variant_quantity_max' | t}}", - "ofn-disable-scroll" => true, - "ng-debounce" => "500", - onwheel: "this.blur()", - min: "{{variant.line_item.quantity}}", - name: "variant_attributes[{{::variant.id}}][max_quantity]", - id: "variants_{{::variant.id}}_max"} + %button.add-variant{type: "button", ng: {if: "!variant.line_item.quantity", click: "addBulk(1)", disabled: "!canAdd(1)"}} + {{ "js.shop_variant_no_group_buy.add" | t }} + %button.bulk-buy.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "addBulk(0)"}}> + {{ variant.line_item.quantity }} + %button.bulk-buy.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "addBulk(0)"}} + {{ variant.line_item.max_quantity || "-" }} + %br + .variant-quantity-display{ng: {class: "{visible: variant.line_item.quantity}"}} + {{ "js.shop_variant_no_group_buy.in_cart" | t:{quantity: ''} }} + %input{type: :hidden, + name: "variants[{{::variant.id}}]", + ng: {model: "variant.line_item.quantity"}} + %input{type: :hidden, + name: "variants[{{::variant.id}}]", + ng: {model: "variant.line_item.max_quantity"}} diff --git a/app/assets/stylesheets/darkswarm/_shop-inputs.scss b/app/assets/stylesheets/darkswarm/_shop-inputs.scss index 21e2267aa4..8a8b030097 100644 --- a/app/assets/stylesheets/darkswarm/_shop-inputs.scss +++ b/app/assets/stylesheets/darkswarm/_shop-inputs.scss @@ -6,47 +6,6 @@ .darkswarm { // #search @include placeholder(rgba(0, 0, 0, 0.4), #777); - - // ordering - product { - // BULK - - input.bulk { - width: 5rem; - - @include breakpoint(desktop) { - width: 4rem; - } - - @include breakpoint(tablet) { - width: 3.5rem; - } - - @include breakpoint(mobile) { - width: 2.8rem; - } - } - - input.bulk.first { - border-right: 0; - } - - input.bulk.second { - border-left: 0; - } - - .bulk-input-container { - float: right; - - @include breakpoint(phablet) { - float: left !important; - } - - .bulk-input { - float: left; - } - } - } } // Components to add variants to cart and change quanities @@ -106,3 +65,29 @@ button.variant-quantity { visibility: visible; } } + +button.bulk-buy.variant-quantity { + background-color: transparent; + border: .1em solid $grey-200; + color: inherit; +} +button.bulk-buy-add.variant-quantity { + width: 2.5rem +} +span.bulk-buy.variant-quantity { + border: .1em solid $grey-200; + height: 2.5rem; + display: inline-block; + min-width: 3em; + padding: .5em; + text-align: center; + vertical-align: top; +} +.variant-bulk-buy-price-summary { + color: $disabled-med; + margin-bottom: 1em; +} +.variant-bulk-buy-quantity-label { + font-size: 0.875rem; + margin-bottom: .5em; +} diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index be28288e05..6cdc2bccb3 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -243,20 +243,24 @@ feature "As a consumer I want to shop with a distributor", js: true do it "should save group buy data to the cart and display it on shopfront reload" do # -- Quantity click_add_bulk_to_cart variant, 6 + close_modal expect(page).to have_in_cart product.name toggle_cart expect(order.reload.line_items.first.quantity).to eq(6) # -- Max quantity - click_add_bulk_max_to_cart variant, 7 + open_bulk_quantity_modal(variant) + click_add_bulk_max_to_cart variant, 1 expect(order.reload.line_items.first.max_quantity).to eq(7) # -- Reload visit shop_path - expect(page).to have_field "variants[#{variant.id}]", with: 6 - expect(page).to have_field "variant_attributes[#{variant.id}][max_quantity]", with: 7 + within_variant(variant) do + expect(page).to have_selector "button.bulk-buy:nth-of-type(1)", text: "6" + expect(page).to have_selector "button.bulk-buy:nth-last-of-type(1)", text: "7" + end end end end @@ -372,12 +376,14 @@ feature "As a consumer I want to shop with a distributor", js: true do # -- Page updates # Update amount in cart - expect(page).to have_field "variant_attributes[#{variant.id}][max_quantity]", with: '0', disabled: true + within_variant(variant) do + expect(page).to have_button "Add", disabled: true + expect(page).to have_no_content "in cart" + end # Update amount available in product list - # If amount falls to zero, variant should be greyed out and input disabled + # If amount falls to zero, variant should be greyed out expect(page).to have_selector "#variant-#{variant.id}.out-of-stock" - expect(page).to have_selector "#variants_#{variant.id}_max[disabled='disabled']" end end @@ -400,7 +406,7 @@ feature "As a consumer I want to shop with a distributor", js: true do it "does not update max_quantity" do click_add_bulk_to_cart variant, 2 - click_add_bulk_max_to_cart variant, 3 + click_add_bulk_max_to_cart variant, 1 close_modal variant.update! on_hand: 1 @@ -412,8 +418,10 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(page).to have_content "#{product.name} - #{variant.unit_to_display} now only has 1 remaining" end - expect(page).to have_field "variants[#{variant.id}]", with: '1' - expect(page).to have_field "variant_attributes[#{variant.id}][max_quantity]", with: '3' + within_variant(variant) do + expect(page).to have_selector "button.bulk-buy:nth-of-type(1)", text: "1" + expect(page).to have_selector "button.bulk-buy:nth-last-of-type(1)", text: "3" + end end end end diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 09e377d510..11a79832a5 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -6,12 +6,6 @@ module ShopWorkflow end def wait_for_cart - # Wait for debounce - # - # The auto-submit on these specific form elements (add to cart) now has a small built-in - # waiting period before submitting the data... - sleep 0.6 - within find_body do # We ignore visibility in case the cart dropdown is not open. within '.cart-sidebar', visible: false do @@ -67,18 +61,21 @@ module ShopWorkflow def click_add_bulk_to_cart(variant = nil, quantity = 1) within_variant(variant) do - input = page.find("input") - new_quantity = input.value.to_i + quantity - fill_in input[:name], with: new_quantity + click_button "Add" + end + within(".reveal-modal") do + (quantity - 1).times do + first(:button, "+").click + end end wait_for_cart end def click_add_bulk_max_to_cart(variant = nil, quantity = 1) - within_variant(variant) do - input = page.find(:field, "variant_attributes[#{variant.id}][max_quantity]") - new_quantity = input.value.to_i + quantity - fill_in input[:name], with: new_quantity + within(".reveal-modal") do + quantity.times do + page.all("button", text: "+").last.click + end end wait_for_cart end @@ -91,6 +88,12 @@ module ShopWorkflow end end + def open_bulk_quantity_modal(variant) + within_variant(variant) do + page.first("button.bulk-buy").click + end + end + def toggle_accordion(name) find("dd a", text: name).click end diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index 1230517d38..f493bcc3ce 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -54,6 +54,10 @@ module UIComponentHelper end end + def close_modal + find("a.close-reveal-modal").click + end + def have_reset_password have_content "An email with instructions on resetting your password has been sent!" end