Replace quantity input with add-remove buttons

The new mobile friendly design contains a nice "Add" button to add
variants to your cart. Once you have the variant in you cart, it's
replaced by plus and minus buttons to adjust the quantity.

Other languages have longer words than "Add" which need to fit on the
button. Since the add button and the +/- buttons should have the same
width, I widened them a little bit so that they fit the longest words
Aggiungi and Добавить.
This commit is contained in:
Maikel Linke
2020-06-03 17:12:36 +10:00
parent 35747dc2b1
commit 59c13b97ea
6 changed files with 111 additions and 86 deletions

View File

@@ -11,3 +11,11 @@ Darkswarm.directive "shopVariant", ->
], (new_value, old_value) ->
return if old_value[0] == null && new_value[0] == null
Cart.adjust($scope.variant.line_item)
$scope.add = (quantity) ->
$scope.variant.line_item.quantity += quantity
$scope.canAdd = (quantity) ->
variant = $scope.variant
wantedQuantity = variant.line_item.quantity + quantity
variant.on_demand || wantedQuantity <= variant.on_hand

View File

@@ -1,14 +1,14 @@
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::!variant.product.group_buy"}
%input{type: :number,
integer: true,
value: nil,
min: 0,
placeholder: "0",
"ofn-disable-scroll" => true,
"ng-debounce" => "500",
onwheel: "this.blur()",
"ng-model" => "variant.line_item.quantity",
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}",
"ng-disabled" => "!variant.on_demand && variant.on_hand == 0",
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
%button.add-variant{type: "button", ng: {if: "!variant.line_item.quantity", click: "add(1)", disabled: "!canAdd(1)"}}
{{ "js.shop_variant_no_group_buy.add" | t }}
%button.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "add(-1)"}}>
{{ "js.shop_variant_no_group_buy.decrement" | t }}
%button.variant-quantity{type: "button", ng: {if: "variant.line_item.quantity", click: "add(1)", disabled: "!canAdd(1)"}}
{{ "js.shop_variant_no_group_buy.increment" | t }}
%br
.variant-quantity-display{ng: {class: "{visible: variant.line_item.quantity}"}}
{{ "js.shop_variant_no_group_buy.in_cart" | t:{quantity: variant.line_item.quantity} }}
%input{type: :hidden,
name: "variants[{{::variant.id}}]",
ng: {model: "variant.line_item.quantity"}}

View File

@@ -9,54 +9,6 @@
// ordering
product {
input {
@include border-radius(0);
@include csstrans;
margin: 0;
width: 10rem;
display: inline;
@include box-shadow(none);
border-color: #b3b3b3;
text-align: right;
@include breakpoint(desktop) {
width: 8rem;
}
@include breakpoint(tablet) {
width: 7rem;
}
@include breakpoint(phablet) {
float: left !important;
font-size: 0.75rem;
padding-left: 0.25rem;
padding-right: 0.25rem;
}
@include breakpoint(mobile) {
width: 5.8rem;
}
&:hover {
@include box-shadow(none);
border-color: #888;
background-color: #fafafa;
}
&:active, &:focus, &.active {
@include box-shadow(none);
background-color: #f9f4b9;
border-color: #666;
}
}
// BULK
input.bulk {
@@ -96,3 +48,61 @@
}
}
}
// Components to add variants to cart and change quanities
//
// They are not nested so that they can be used in modals.
button.add-variant, button.variant-quantity {
height: 2.5rem;
border-radius: 0;
background-color: $orange-500;
color: white;
// Override foundation button styles:
font-size: 1rem;
margin: 0;
padding: 0;
transition: none;
&[disabled] {
&:hover, &:focus {
background-color: $orange-500;
}
}
&:nth-of-type(1) {
border-bottom-left-radius: 0.25em;
border-top-left-radius: 0.25em;
}
&:nth-last-of-type(1) {
border-top-right-radius: 0.25em;
border-bottom-right-radius: 0.25em;
}
}
button.add-variant {
min-width: 6rem;
padding: 0 1em;
&[disabled] {
&:hover, &:focus {
background-color: $orange-500;
}
}
}
button.variant-quantity {
width: 3rem;
&:nth-of-type(1) {
border-right: .1em solid $orange-400;
}
}
.variant-quantity-display {
display: inline-block;
font-size: 0.875em;
margin-top: 0.25em;
text-align: center;
width: 6rem;
visibility: hidden;
&.visible {
visibility: visible;
}
}

View File

@@ -2726,6 +2726,11 @@ See the %{link} to find out more about %{sitename}'s features and to start using
in your cart have reduced. Here's what's changed:
now_out_of_stock: is now out of stock.
only_n_remainging: "now only has %{num} remaining."
shop_variant_no_group_buy:
add: "Add"
increment: "" # U+FF0B Fullwidth Plus Sign
decrement: "" # U+FF0D Fullwidth Hyphen-Minus
in_cart: "%{quantity} in cart"
variants:
on_demand:
"yes": "On demand"

View File

@@ -294,19 +294,21 @@ feature "As a consumer I want to shop with a distributor", js: true do
click_add_to_cart variant, 10
expect(page).to have_field "variants[#{variant.id}]", with: '10'
within_variant(variant) do
expect(page).to have_content "10 in cart"
end
end
it "alerts us when we enter a quantity greater than the stock available" do
variant.update on_hand: 5
visit shop_path
accept_alert 'Insufficient stock available, only 5 remaining' do
fill_in "variants[#{variant.id}]", with: '10'
end
click_add_to_cart variant, 5
expect(page).to have_field "variants[#{variant.id}]", with: '5'
within_variant(variant) do
expect(page).to have_content "5 in cart"
expect(page).to have_button "", disabled: true
end
end
describe "when a product goes out of stock just before it's added to the cart" do
@@ -325,8 +327,13 @@ 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 "variants[#{variant.id}]", with: '0', disabled: true
expect(page).to have_field "variants[#{variant2.id}]", with: ''
within_variant(variant) do
expect(page).to have_button "Add", disabled: true
expect(page).to have_no_content "in cart"
end
within_variant(variant2) do
expect(page).to have_button "Add", disabled: false
end
# Update amount available in product list
# If amount falls to zero, variant should be greyed out and input disabled
@@ -352,7 +359,11 @@ feature "As a consumer I want to shop with a distributor", js: true do
variant.update! on_hand: 0
# -- Messaging
click_add_bulk_max_to_cart variant
within(".reveal-modal") do
page.all("button", text: "").last.click
end
close_modal
wait_for_cart
within(".out-of-stock-modal") do
expect(page).to have_content "stock levels for one or more of the products in your cart have reduced"
@@ -390,6 +401,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
close_modal
variant.update! on_hand: 1
@@ -554,9 +566,10 @@ feature "As a consumer I want to shop with a distributor", js: true do
end
# Removes the item from the client-side cart and marks the variant as unavailable
expect(page).to have_field "variants[#{variant.id}]", with: '0', disabled: true
expect(page).to have_selector "#variant-#{variant.id}.out-of-stock"
expect(page).to have_selector "#variants_#{variant.id}[ofn-on-hand='0']"
expect(page).to have_selector "#variants_#{variant.id}[disabled='disabled']"
within_variant(variant) do
expect(page).to have_button "Add", disabled: true
expect(page).to have_no_content "in cart"
end
end
end

View File

@@ -50,28 +50,17 @@ module ShopWorkflow
end
# Add an item to the cart
#
# At the moment, the user enters the quantity into an input field.
# But with the coming mobile-friendly UX, the user will click a button to
# add an item, hence the naming.
#
# This is temporary code. The duplication will be removed by the mobile
# product listings feature. This has been backported to avoid merge
# conflicts and to make the current build more stable.
def click_add_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"
(quantity - 1).times { click_button "" }
end
wait_for_cart
end
def click_remove_from_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
quantity.times { click_button "" }
end
wait_for_cart
end