spree_storefront 5.0.4 → 5.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/line_items_controller.rb +14 -7
  3. data/app/controllers/spree/products_controller.rb +1 -1
  4. data/app/controllers/spree/search_controller.rb +1 -1
  5. data/app/controllers/spree/store_controller.rb +17 -15
  6. data/app/helpers/spree/cart_helper.rb +1 -1
  7. data/app/helpers/spree/filters_helper.rb +5 -1
  8. data/app/helpers/spree/products_helper.rb +5 -1
  9. data/app/helpers/spree/storefront_helper.rb +1 -0
  10. data/app/javascript/spree/storefront/controllers/card_validation_controller.js +2 -0
  11. data/app/javascript/spree/storefront/controllers/cart_controller.js +5 -0
  12. data/app/views/devise/passwords/edit.html.erb +1 -1
  13. data/app/views/devise/registrations/new.html.erb +1 -1
  14. data/app/views/devise/shared/_links.html.erb +3 -3
  15. data/app/views/spree/addresses/edit.html.erb +2 -2
  16. data/app/views/spree/checkout/_address.html.erb +3 -4
  17. data/app/views/spree/checkout/_coupon_code.html.erb +1 -1
  18. data/app/views/spree/checkout/_delivery.html.erb +1 -2
  19. data/app/views/spree/checkout/_missing_all_line_items.html.erb +2 -2
  20. data/app/views/spree/checkout/_payment_methods.html.erb +1 -1
  21. data/app/views/spree/checkout/_summary.html.erb +45 -44
  22. data/app/views/spree/checkout/payment/_gateway.html.erb +12 -12
  23. data/app/views/spree/line_items/destroy.turbo_stream.erb +14 -8
  24. data/app/views/spree/seo/sitemap.xml.erb +2 -2
  25. data/app/views/themes/default/spree/account/_order.html.erb +5 -5
  26. data/app/views/themes/default/spree/checkout/complete.html.erb +1 -1
  27. data/app/views/themes/default/spree/orders/_line_item.html.erb +3 -3
  28. data/app/views/themes/default/spree/page_sections/_featured_posts.html.erb +56 -0
  29. data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +1 -1
  30. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +2 -2
  31. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +4 -5
  32. data/app/views/themes/default/spree/policies/show.html.erb +11 -7
  33. data/app/views/themes/default/spree/posts/_post.html.erb +20 -11
  34. data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +4 -4
  35. data/app/views/themes/default/spree/products/_details.html.erb +1 -1
  36. data/app/views/themes/default/spree/products/_json_ld.html.erb +1 -1
  37. data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +1 -1
  38. data/app/views/themes/default/spree/products/_media_gallery.html.erb +1 -2
  39. data/app/views/themes/default/spree/products/filters/_availability.html.erb +1 -1
  40. data/app/views/themes/default/spree/products/filters/_price.html.erb +4 -4
  41. data/app/views/themes/default/spree/shared/_cart_icon.html.erb +4 -2
  42. data/app/views/themes/default/spree/shared/_cart_pane.html.erb +5 -2
  43. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +2 -2
  44. data/config/locales/en.yml +8 -0
  45. data/lib/generators/spree/storefront/theme/templates/model.rb.tt +91 -4
  46. metadata +7 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2558511bde3c23461f7d59985b314ea15d992912d29ba2566ce9d057b6a8cff2
4
- data.tar.gz: 99bff2e39e457da5b2bec3fab6ab64b5953128bae0b2a42945c19e16d2b682f3
3
+ metadata.gz: d8b5f53e77331921922ac1da27123087c2b06413b7e77bb9061709a3f4c331a6
4
+ data.tar.gz: 72d769742b732a7d2500dc4ce2ab6d25217198ac40d5010273b9ffb55a815a01
5
5
  SHA512:
6
- metadata.gz: 709743a94e95bed8ef6a542231843103f60bf7699c610da106d96cd73178fe8a354eeeed5960d71349319ab77ee2915e11e97ec6efd12642f0af3d5af96175a5
7
- data.tar.gz: bf929b7256f749ce99590d6f293326f157e2489700411d25e513a9ec0c4359d1352519fb1e1dea0cedfb6881771085e634af4b25b8f012ee4dbee474bd2e81f5
6
+ metadata.gz: e9eb50e07eee8427553b3ff7afb6e4e87a409c7a2bfdd0aa1fae44d31e146ef1595750f79e3a1e4a296390dfc3c9e9b589d17f3e3bf7131f277f859be4ea841d
7
+ data.tar.gz: 20e8fc5511fbedf98f50cdfe492e4765ca15fe39de324bd4988a2d03ac8b80b5e0a098cb59f0488d73b03cb75f086f02ef3bea757dbd6d0b5e3c434286cf7d88
@@ -22,8 +22,6 @@ module Spree
22
22
  quantity: @quantity,
23
23
  options: options)
24
24
 
25
- flash.now[:error] = result.value.errors.full_messages.to_sentence if result.failure?
26
-
27
25
  @line_item = result.value
28
26
 
29
27
  if result.success?
@@ -45,9 +43,12 @@ module Spree
45
43
  quantity = line_item_params[:quantity]&.to_i || 1
46
44
  result = cart_set_item_quantity_service.call(order: @order, line_item: @line_item, quantity: quantity)
47
45
 
48
- @error = result.value.errors.full_messages.to_sentence if result.failure?
49
-
50
- load_line_items if result.success?
46
+ if result.success?
47
+ load_line_items
48
+ else
49
+ @error = result.value.errors.full_messages.to_sentence
50
+ flash.now[:error] = @error
51
+ end
51
52
 
52
53
  respond_to do |format|
53
54
  format.turbo_stream
@@ -57,9 +58,15 @@ module Spree
57
58
 
58
59
  def destroy
59
60
  result = cart_remove_line_item_service.call(order: @order, line_item: @line_item)
60
- load_line_items if result.success?
61
61
 
62
- track_event('product_removed', { line_item: @line_item })
62
+ if result.success?
63
+ load_line_items
64
+
65
+ track_event('product_removed', { line_item: @line_item })
66
+ else
67
+ @error = result.value.errors.full_messages.to_sentence
68
+ flash.now[:error] = @error
69
+ end
63
70
 
64
71
  respond_to do |format|
65
72
  format.turbo_stream
@@ -23,7 +23,7 @@ module Spree
23
23
  load_product
24
24
  # An interesting thing is that since we're querying the translations table (in the multi_search),
25
25
  # when using not default locale, our related products are different for different locales.
26
- @products = current_store.products.active(current_currency).where.not(id: @product.id).
26
+ @products = storefront_products_scope.where.not(id: @product.id).
27
27
  multi_search(@product.name).includes(storefront_products_includes).
28
28
  limit(@section.preferred_max_products_to_show)
29
29
  end
@@ -13,7 +13,7 @@ module Spree
13
13
  @taxons = []
14
14
 
15
15
  if query.present? && query.length >= Spree::Storefront::Config.search_min_query_length
16
- products_scope = current_store.products.active(current_currency).multi_search(query)
16
+ products_scope = storefront_products_scope.multi_search(query)
17
17
  @products = products_scope.includes(storefront_products_includes)
18
18
  @taxons = current_store.taxons.search_by_name(query)
19
19
  end
@@ -116,29 +116,31 @@ module Spree
116
116
  end
117
117
 
118
118
  def storefront_products_scope
119
- current_store.products.active(current_currency)
119
+ @storefront_products_scope ||= current_store.products.active(current_currency)
120
120
  end
121
121
 
122
122
  def default_products_finder_params
123
- taxon = @taxon || current_taxon
123
+ @default_products_finder_params ||= begin
124
+ taxon = @taxon || current_taxon
124
125
 
125
- filter = permitted_products_params.fetch(:filter, {}).dup
126
+ filter = permitted_products_params.fetch(:filter, {}).dup
126
127
 
127
- filter[:taxon_ids] ||= [taxon&.id.to_s].compact
128
- filter[:taxons] = filter[:taxon_ids].join(',')
128
+ filter[:taxon_ids] ||= [taxon&.id.to_s].compact
129
+ filter[:taxons] = filter[:taxon_ids].join(',')
129
130
 
130
- if filter.key?(:min_price) || filter.key?(:max_price)
131
- min_price = filter[:min_price].presence || 0
132
- max_price = filter[:max_price].presence || 'Infinity'
131
+ if filter.key?(:min_price) || filter.key?(:max_price)
132
+ min_price = filter[:min_price].presence || 0
133
+ max_price = filter[:max_price].presence || 'Infinity'
133
134
 
134
- filter[:price] = [min_price, max_price].compact.join(',')
135
- end
135
+ filter[:price] = [min_price, max_price].compact.join(',')
136
+ end
136
137
 
137
- permitted_products_params.merge(
138
- store: current_store,
139
- filter: filter,
140
- currency: current_currency
141
- )
138
+ permitted_products_params.merge(
139
+ store: current_store,
140
+ filter: filter,
141
+ currency: current_currency
142
+ )
143
+ end
142
144
  end
143
145
 
144
146
  def storefront_products
@@ -22,7 +22,7 @@ module Spree
22
22
  class: opts[:class],
23
23
  data: {
24
24
  'quantity-picker-target': opts[:action],
25
- action: "click->quantity-picker##{opts[:action]} click->cart#disableCart"
25
+ action: "click->quantity-picker##{opts[:action]} click->cart#disableCart turbo-stream-form:submit-end->cart#enableCart"
26
26
  }
27
27
  )
28
28
  end
@@ -76,10 +76,14 @@ module Spree
76
76
  if filter_selected
77
77
  default_storefront_filter_values_scope
78
78
  else
79
- Spree::OptionValue.for_products(storefront_products_for_filters).distinct
79
+ all_option_values_scope
80
80
  end
81
81
  end
82
82
 
83
+ def all_option_values_scope
84
+ @all_option_values_scope ||= Spree::OptionValue.for_products(storefront_products_scope).distinct
85
+ end
86
+
83
87
  def filter_values_for_filter(filter)
84
88
  selected = single_option_filter_selected?(filter.name)
85
89
  if filter.option_values.loaded?
@@ -157,7 +157,7 @@ module Spree
157
157
  {
158
158
  '@type' => 'ListItem',
159
159
  'position' => index + 1,
160
- 'url' => spree.product_url(product_slug)
160
+ 'url' => spree.product_url(product_slug, host: current_store.url_or_custom_domain)
161
161
  }
162
162
  end
163
163
  end
@@ -201,5 +201,9 @@ module Spree
201
201
 
202
202
  Spree::ColorsPreviewStylesPresenter.new(option_type.option_values.map { |ov| { name: ov.name, filter_name: ov.name } }).to_s
203
203
  end
204
+
205
+ def product_properties(product)
206
+ product.product_properties.joins(:property).merge(Spree::Property.available_on_front_end).sort_by_property_position
207
+ end
204
208
  end
205
209
  end
@@ -53,6 +53,7 @@ module Spree
53
53
 
54
54
  def svg_country_icon(country_code)
55
55
  country_code = :us if country_code.to_s.downcase == 'en'
56
+ country_code = :jp if country_code.to_s.downcase == 'ja'
56
57
  tag.span(class: "fi fi-#{country_code.downcase}")
57
58
  end
58
59
 
@@ -56,6 +56,8 @@ export default class extends Controller {
56
56
  }
57
57
 
58
58
  updateCardIcon(cardType) {
59
+ cardType = (cardType === "mastercard" ? "master" : cardType)
60
+
59
61
  const iconElement = document.getElementById(`credit-card-icon-${cardType}`)
60
62
  if (iconElement) {
61
63
  this.typeContainerTarget.innerHTML = iconElement.innerHTML
@@ -7,4 +7,9 @@ export default class extends Controller {
7
7
  this.containerTarget.classList.add('pointer-events-none', 'opacity-50')
8
8
  this.spinnerTarget.classList.remove('hidden')
9
9
  }
10
+
11
+ enableCart() {
12
+ this.containerTarget.classList.remove('pointer-events-none', 'opacity-50')
13
+ this.spinnerTarget.classList.add('hidden')
14
+ }
10
15
  }
@@ -6,7 +6,7 @@
6
6
  <div class="flex flex-col mb-4">
7
7
  <%= f.label :password, Spree.t(:password) %>
8
8
  <% if @minimum_password_length %>
9
- <em>(<%= @minimum_password_length %> characters minimum)</em>
9
+ <em><%= Spree.t(:minimum_password_length, count: @minimum_password_length) %></em>
10
10
  <% end %>
11
11
  <%= f.password_field :password, autofocus: true, autocomplete: "new-password", class: 'text-input', required: true %>
12
12
  </div>
@@ -10,7 +10,7 @@
10
10
  <div class="flex flex-col mb-4">
11
11
  <%= f.label :password, Spree.t(:password) %>
12
12
  <% if @minimum_password_length %>
13
- <em>(<%= @minimum_password_length %> characters minimum)</em>
13
+ <em><%= Spree.t(:minimum_password_length, count: @minimum_password_length) %></em>
14
14
  <% end %>
15
15
  <%= f.password_field :password, autocomplete: "new-password", class: 'text-input', required: true %>
16
16
  </div>
@@ -9,14 +9,14 @@
9
9
  <%= link_to Spree.t(:forgot_password), new_password_path(resource_name) %>
10
10
  <% end %>
11
11
  <%- if devise_mapping.confirmable? && controller_name != 'user_confirmations' %>
12
- <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
12
+ <%= link_to Spree.t(:didn_t_receive_confirmation_instructions), new_confirmation_path(resource_name) %>
13
13
  <% end %>
14
14
  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'user_unlocks' %>
15
- <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
15
+ <%= link_to Spree.t(:didn_t_receive_unlock_instructions), new_unlock_path(resource_name) %>
16
16
  <% end %>
17
17
  <%- if devise_mapping.omniauthable? %>
18
18
  <%- resource_class.omniauth_providers.each do |provider| %>
19
- <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
19
+ <%= button_to Spree.t(:sign_in_with_provider, provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
20
20
  <% end %>
21
21
  <% end %>
22
22
  </div>
@@ -38,13 +38,13 @@
38
38
  <%= check_box_tag "default_shipping", "true", @address.user_default_shipping?,
39
39
  class: 'input-checkbox input-address-default',
40
40
  disabled: @address.user_default_shipping? %>
41
- Set as default delivery address
41
+ <%= Spree.t("address_book.set_as_default_delivery_address") %>
42
42
  <% end %>
43
43
  <%= label_tag "default_billing", class: "flex items-center gap-2 text-sm mb-4" do %>
44
44
  <%= check_box_tag "default_billing", "true", @address.user_default_billing?,
45
45
  class: 'input-checkbox input-address-default',
46
46
  disabled: @address.user_default_billing? %>
47
- Set as default billing address
47
+ <%= Spree.t("address_book.set_as_default_billing_address") %>
48
48
  <% end %>
49
49
  </div>
50
50
  <div class="border-t border-default -mx-4 lg:mx-0 px-4 flex justify-end items-center gap-4 py-6 lg:px-8">
@@ -49,7 +49,7 @@
49
49
  <% end %>
50
50
  </div>
51
51
  </label>
52
- </label>
52
+ </div>
53
53
  </li>
54
54
  </ul>
55
55
  </div>
@@ -115,8 +115,7 @@
115
115
  <% unless try_spree_current_user %>
116
116
  <% if already_have_an_account? %>
117
117
  <div class="py-2 text-sm">
118
- It seems you already have an account with us. Please
119
- <%= link_to Spree.t(:login), spree_login_path, class: 'text-primary font-semibold' %> to continue.
118
+ <%= Spree.t("storefront.checkout.it_seems_you_already_have_an_account_html", link: link_to(Spree.t(:login), spree_login_path, class: 'text-primary font-semibold')) %>
120
119
  </div>
121
120
  <% end %>
122
121
  <% end %>
@@ -132,7 +131,7 @@
132
131
  address_name: address_name,
133
132
  address_form: address_form,
134
133
  address_type: address_type,
135
- address: Spree::Address.new(country: current_store.default_country, user: try_spree_current_user),
134
+ address: address_form.object.persisted? ? address_form.object : Spree::Address.new(country: current_store.default_country, user: try_spree_current_user),
136
135
  form: form
137
136
  } %>
138
137
  </div>
@@ -8,7 +8,7 @@
8
8
  aria: { label: Spree.t('cart_page.add_promo_code') },
9
9
  data: { 'enable-button-target': 'input' },
10
10
  required: true %>
11
- <%= button_tag 'Apply', class: 'min-h-full ml-3 btn-primary !px-4 !py-3', data: { 'enable-button-target': 'button' }, disabled: true %>
11
+ <%= button_tag Spree.t(:apply), class: 'min-h-full ml-3 btn-primary !px-4 !py-3', data: { 'enable-button-target': 'button' }, disabled: true %>
12
12
  </div>
13
13
  <% end %>
14
14
  <% elsif promotion.present? %>
@@ -6,7 +6,7 @@
6
6
  <div id="shipping-method">
7
7
  <% if @order.backordered_variants.any? %>
8
8
  <div class="alert rounded border border-default text-sm p-5 mb-6">
9
- Some products in your cart will be dispatched a bit later than the rest of your order:
9
+ <%= Spree.t("storefront.checkout.backorder_notice") %>
10
10
  <ul class="list-disc list-inside flex-col flex space-y-1 mt-2">
11
11
  <% @order.backordered_variants.each do |variant| %>
12
12
  <li><%= variant.name %></li>
@@ -67,4 +67,3 @@
67
67
  </div>
68
68
  </div>
69
69
  <% end %>
70
-
@@ -7,8 +7,8 @@
7
7
  <p class="mb-4"><%= Spree.t('errors.messages.no_shipping_methods_available') %> </p>
8
8
 
9
9
  <div class="flex justify-end items-center flex-wrap mt-6">
10
- <%= link_to 'Return to cart', spree.cart_path, class: 'mx-4 py-4', target: :_top %>
11
- <%= link_to 'Close', checkout_state_path(@order.token, @order.state), class: 'btn-primary font-semibold checkout-content-save-continue-button my-5 ml-4 !py-4', target: :_top %>
10
+ <%= link_to Spree.t("storefront.checkout.return_to_cart"), spree.cart_path, class: 'mx-4 py-4', target: :_top %>
11
+ <%= link_to Spree.t(:close), checkout_state_path(@order.token, @order.state), class: 'btn-primary font-semibold checkout-content-save-continue-button my-5 ml-4 !py-4', target: :_top %>
12
12
  </div>
13
13
  </div>
14
14
  </div>
@@ -66,7 +66,7 @@
66
66
  class="btn-primary w-full lg:w-2/5 font-semibold checkout-content-save-continue-button my-5 !py-4"
67
67
  >
68
68
  <%= render 'button_processing', is_hidden: true %>
69
- <%= Spree.t(:pay).titleize %>
69
+ <%= Spree.t(:pay) %>
70
70
  </button>
71
71
  </div>
72
72
  <% end %>
@@ -47,70 +47,71 @@
47
47
  <span>
48
48
  <%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency).to_html %>
49
49
  </span>
50
- <% end %>
50
+ </div>
51
51
  <% end %>
52
52
  <% end %>
53
- <% elsif order.state == 'address' %>
54
- <div class="flex justify-between items-center mb-2">
55
- <span><%= Spree.t(:shipping) %>:</span>
56
- <span class="text-xs text-gray-500"><%= Spree.t('storefront.checkout.calculated_at_next_step') %></span>
57
- </div>
58
53
  <% end %>
54
+ <% elsif order.state == 'address' %>
55
+ <div class="flex justify-between items-center mb-2">
56
+ <span><%= Spree.t(:shipping) %>:</span>
57
+ <span class="text-xs text-gray-500"><%= Spree.t('storefront.checkout.calculated_at_next_step') %></span>
58
+ </div>
59
+ <% end %>
59
60
 
60
- <% if order.payment? || order.completed? %>
61
- <% cache spree_base_cache_scope.call(order.all_adjustments.nonzero.tax.eligible.cache_key_with_version) do %>
62
- <% order.all_adjustments.nonzero.tax.eligible.group_by(&:label).each do |label, adjustments| %>
63
- <div class="flex justify-between items-center mb-2">
64
- <span><%= label %></span>
61
+ <% if order.payment? || order.completed? %>
62
+ <% cache spree_base_cache_scope.call(order.all_adjustments.nonzero.tax.eligible.cache_key_with_version) do %>
63
+ <% order.all_adjustments.nonzero.tax.eligible.group_by(&:label).each do |label, adjustments| %>
64
+ <div class="flex justify-between items-center mb-2">
65
+ <span><%= label %></span>
65
66
 
66
- <% tax_total = Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
67
- <span><%= tax_total.to_html %></span>
68
- </div>
69
- <% end %>
67
+ <% tax_total = Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
68
+ <span><%= tax_total.to_html %></span>
69
+ </div>
70
70
  <% end %>
71
71
  <% end %>
72
+ <% end %>
72
73
 
73
- <% if order.adjustments.nonzero.non_tax.eligible.exists? %>
74
- <% order.adjustments.nonzero.non_tax.eligible.each do |adjustment| %>
75
- <div class="flex justify-between items-center mb-2">
74
+ <% if order.adjustments.nonzero.non_tax.eligible.exists? %>
75
+ <% order.adjustments.nonzero.non_tax.eligible.each do |adjustment| %>
76
+ <div class="flex justify-between items-center mb-2">
76
77
  <span>
77
78
  <%= adjustment.label %>:
78
79
  </span>
79
- <span>
80
+ <span>
80
81
  <%= adjustment.display_amount.to_html %>
81
82
  </span>
82
- </div>
83
- <% end %>
84
- <% end %>
85
-
86
- <% if order.respond_to?(:gift_card) && order.gift_card.present? %>
87
- <div class="flex justify-between items-center mb-2">
88
- <span><%= Spree.t(:gift_card) %>:</span>
89
- <span>-<%= order.display_gift_card_total %></span>
90
- </div>
91
- <% elsif order.using_store_credit? %>
92
- <div class="flex justify-between items-center mb-2">
93
- <span>Store credit:</span>
94
- <span><%= order.display_total_applied_store_credit %></span>
95
83
  </div>
96
84
  <% end %>
85
+ <% end %>
97
86
 
98
- <div>
99
- <div class="flex justify-between items-center">
100
- <span class="font-bold text-lg"><%= Spree.t(:total) %></span>
101
- <div class="">
102
- <span class="text-xs mr-1"><%= order.currency.upcase %></span>
103
- <span class="font-semibold text-lg inline" id='summary-order-total' data-currency="<%= Money::Currency.find(order.currency).symbol %>">
87
+ <% if order.respond_to?(:gift_card) && order.gift_card.present? %>
88
+ <div class="flex justify-between items-center mb-2">
89
+ <span><%= Spree.t(:gift_card) %>:</span>
90
+ <span>-<%= order.display_gift_card_total %></span>
91
+ </div>
92
+ <% elsif order.using_store_credit? %>
93
+ <div class="flex justify-between items-center mb-2">
94
+ <span><%= Spree.t(:store_credit_name) %>:</span>
95
+ <span><%= order.display_total_applied_store_credit %></span>
96
+ </div>
97
+ <% end %>
98
+
99
+ <div>
100
+ <div class="flex justify-between items-center">
101
+ <span class="font-bold text-lg"><%= Spree.t(:total) %></span>
102
+ <div class="">
103
+ <span class="text-xs mr-1"><%= order.currency.upcase %></span>
104
+ <span class="font-semibold text-lg inline" id='summary-order-total' data-currency="<%= Money::Currency.find(order.currency).symbol %>">
104
105
  <%= order.display_total_minus_store_credits.to_html %>
105
106
  </span>
106
- </div>
107
107
  </div>
108
108
  </div>
109
109
  </div>
110
- <% end %>
111
-
112
- <div id="checkout-message" class="mt-8">
113
- <%= current_store.checkout_message if current_store.checkout_message.present? %>
114
110
  </div>
111
+ <% end %>
112
+
113
+ <div id="checkout-message" class="mt-8">
114
+ <%= current_store.checkout_message if current_store.checkout_message.present? %>
115
115
  </div>
116
- <% end %>
116
+ </div>
117
+ <% end %>
@@ -11,7 +11,7 @@
11
11
  <div class="form-group mb-3 relative">
12
12
  <% options_hash = Rails.env.production? ? {autocomplete: 'off'} : {} %>
13
13
  <label for="card_number" class="block text-xs text-neutral-600 mb-1"><%= Spree.t(:card_number) %></label>
14
- <%= text_field_tag "#{param_prefix}[number]", '',
14
+ <%= text_field_tag "#{param_prefix}[number]", '',
15
15
  options_hash.merge(
16
16
  id: 'card_number',
17
17
  data: { card_validation_target: "number" },
@@ -23,7 +23,7 @@
23
23
  required: true
24
24
  )
25
25
  %>
26
- <div class="absolute right-2 top-7"
26
+ <div class="absolute right-2 top-7"
27
27
  data-card-validation-target="typeContainer"
28
28
  id="credit-card-type-container">
29
29
  </div>
@@ -32,37 +32,37 @@
32
32
  <div class="flex gap-3">
33
33
  <div class="form-group">
34
34
  <label for="card_expiry" class="block text-xs text-neutral-600 mb-1"><%= Spree.t(:expiration_date) %></label>
35
- <%= text_field_tag "#{param_prefix}[expiry]", '',
36
- id: 'card_expiry',
35
+ <%= text_field_tag "#{param_prefix}[expiry]", '',
36
+ id: 'card_expiry',
37
37
  class: 'text-input',
38
38
  data: {
39
39
  card_validation_target: "expiry"
40
40
  },
41
- placeholder: "MM/YYYY",
41
+ placeholder: Spree.t(:card_expiration_placeholder),
42
42
  required: true
43
43
  %>
44
44
  </div>
45
45
  <div class="form-group">
46
46
  <label for="card_code" class="block text-xs text-neutral-600 mb-1"><%= Spree.t(:cvv) %></label>
47
- <%= text_field_tag "#{param_prefix}[verification_value]", '',
47
+ <%= text_field_tag "#{param_prefix}[verification_value]", '',
48
48
  options_hash.merge(
49
- id: 'card_code',
50
- class: 'text-input',
49
+ id: 'card_code',
50
+ class: 'text-input',
51
51
  data: { card_validation_target: "cvv" },
52
52
  size: 4,
53
53
  maxlength: 4,
54
54
  pattern: '[0-9]*',
55
55
  inputmode: 'numeric',
56
- placeholder: Spree.t(:cvv),
56
+ placeholder: Spree.t(:cvv),
57
57
  required: true
58
- )
58
+ )
59
59
  %>
60
60
  </div>
61
61
  </div>
62
62
 
63
- <%= hidden_field_tag "#{param_prefix}[cc_type]", '',
63
+ <%= hidden_field_tag "#{param_prefix}[cc_type]", '',
64
64
  id: "cc_type",
65
- data: { card_validation_target: "ccType" }
65
+ data: { card_validation_target: "ccType" }
66
66
  %>
67
67
 
68
68
  <% PaymentIcon.credit_cards.each do |card| %>
@@ -1,11 +1,17 @@
1
- <%= turbo_stream.replace_all '.cart-contents' do %>
2
- <%= turbo_frame_tag cart_id(@order), class: 'cart-contents' do %>
3
- <% if @order.line_items.empty? %>
4
- <%= render 'spree/orders/empty' %>
5
- <% else %>
6
- <%= render 'spree/orders/cart' %>
1
+ <% if flash[:error] %>
2
+ <%= spree_turbo_update_flashes %>
3
+ <% else %>
4
+ <%= turbo_stream.replace_all '.cart-contents' do %>
5
+ <%= turbo_frame_tag cart_id(@order), class: 'cart-contents' do %>
6
+ <% if @order.line_items.empty? %>
7
+ <%= render 'spree/orders/empty' %>
8
+ <% else %>
9
+ <%= render 'spree/orders/cart' %>
10
+ <% end %>
11
+
12
+ <%= render_storefront_partials(:remove_from_cart_partials) %>
7
13
  <% end %>
8
14
  <% end %>
9
- <% end %>
10
15
 
11
- <%= spree_turbo_update_cart(@order) %>
16
+ <%= spree_turbo_update_cart(@order) %>
17
+ <% end %>
@@ -12,8 +12,8 @@
12
12
  <% end %>
13
13
  <% end %>
14
14
 
15
- <% cache [current_store.products, current_currency] do %>
16
- <% current_store.products.active(current_currency).find_each do |product| %>
15
+ <% cache [storefront_products_scope, current_currency] do %>
16
+ <% storefront_products_scope.find_each do |product| %>
17
17
  <url>
18
18
  <loc><%= spree_storefront_resource_url(product) %></loc>
19
19
  <lastmod><%= product.updated_at.strftime('%Y-%m-%d') %></lastmod>
@@ -8,16 +8,16 @@
8
8
  <% if order.payment_state == 'void' %>
9
9
  <% if order.order_refunded? %>
10
10
  <span class="badge-refunded">
11
- <%= Spree.t("payment_states.refunded").titleize %>
11
+ <%= Spree.t("payment_states.refunded") %>
12
12
  </span>
13
13
  <% else %>
14
14
  <span class="badge-void">
15
- <%= Spree.t("payment_states.#{order.payment_state}").titleize %>
15
+ <%= Spree.t("payment_states.#{order.payment_state}") %>
16
16
  </span>
17
17
  <% end %>
18
18
  <% else %>
19
19
  <span class="badge-success">
20
- <%= Spree.t("payment_states.#{order.payment_state}").titleize %>
20
+ <%= Spree.t("payment_states.#{order.payment_state}") %>
21
21
  </span>
22
22
  <% end %>
23
23
  <% end %>
@@ -26,11 +26,11 @@
26
26
  <% if order.shipment_state %>
27
27
  <% if order.shipment_state == 'shipped' %>
28
28
  <span class="badge-success">
29
- <%= Spree.t("shipment_states.#{order.shipment_state}").titleize %>
29
+ <%= Spree.t("shipment_states.#{order.shipment_state}") %>
30
30
  </span>
31
31
  <% else %>
32
32
  <span class="badge-<%= order.shipment_state %>">
33
- <%= Spree.t("shipment_states.#{order.shipment_state}").titleize %>
33
+ <%= Spree.t("shipment_states.#{order.shipment_state}") %>
34
34
  </span>
35
35
  <% end %>
36
36
  <% end %>
@@ -24,7 +24,7 @@
24
24
  <div class="mt-3 border-t pt-3">
25
25
  <span class="text-sm"><%= Spree.t(:status) %></span>
26
26
  <% if @order.payment_state.present? %>
27
- <span class="badge-<%= @order.payment_state %>"><%= Spree.t("payment_states.#{@order.payment_state}").titleize %></span>
27
+ <span class="badge-<%= @order.payment_state %>"><%= Spree.t("payment_states.#{@order.payment_state}") %></span>
28
28
  <% else %>
29
29
  <span class="badge-pending"><%= Spree.t(:pending) %></span>
30
30
  <% end %>
@@ -1,5 +1,5 @@
1
- <%= turbo_frame_tag dom_id(line_item), data: { controller: 'reveal' } do %>
2
- <li class="cart-line-item flex items-top py-6 px-4 w-full" data-reveal-target="item">
1
+ <%= turbo_frame_tag dom_id(line_item) do %>
2
+ <li class="cart-line-item flex items-top py-6 px-4 w-full">
3
3
  <div class="line-item-overlay"></div>
4
4
  <div class="cart-product-image flex-shrink-0" id="<%= dom_id(line_item) %>-image" data-turbo-permanent>
5
5
  <% image = line_item.variant.default_image %>
@@ -14,7 +14,7 @@
14
14
  <%= link_to line_item.name, spree_storefront_resource_url(line_item.product), class: 'font-semibold text-text', data: { 'turbo-frame': '_top' } %>
15
15
 
16
16
  <%= form_for line_item, url: spree.line_item_url(line_item, order_token: line_item.order.token), method: :delete, data: { controller: 'turbo-stream-form' } do |item_form| %>
17
- <%= button_tag type: :submit, class: 'remove-line-item-button h-100', data: { action: "click->reveal#hide click->cart#disableCart" } do %>
17
+ <%= button_tag type: :submit, class: 'remove-line-item-button h-100', data: { action: "click->cart#disableCart turbo-stream-form:submit-end->cart#enableCart" } do %>
18
18
  <%= render 'spree/shared/icons/cross', size: 16 %>
19
19
  <% end %>
20
20
  <% end %>
@@ -0,0 +1,56 @@
1
+ <div style='<%= section_styles(section) %>' class='animate-fadeIn'>
2
+ <div class='page-container'>
3
+ <% heading_size =
4
+ case section.preferred_heading_size
5
+ when "small"
6
+ "text-base font-medium"
7
+ when "medium"
8
+ "text-lg lg:text-xl font-medium"
9
+ when "large"
10
+ "text-xl lg:text-2xl font-medium"
11
+ end %>
12
+ <% if section.preferred_heading.present? %>
13
+ <div class='mb-8 flex flex-col'>
14
+ <h3
15
+ class='
16
+ <%= heading_size %> featured-taxon--title font-medium
17
+ text-<%= section.preferred_heading_alignment %>
18
+ '
19
+ data-title="<%= section.preferred_heading.downcase %>"
20
+ style='<%= section_heading_styles(section) %>'
21
+ >
22
+ <%= section.preferred_heading %>
23
+ </h3>
24
+
25
+ <% if section.description.present? %>
26
+ <div class='pt-4 text-<%= section.preferred_description_alignment %>'>
27
+ <%= section.description %>
28
+ </div>
29
+ <% end %>
30
+ </div>
31
+ <% end %>
32
+ <div class='flex h-full relative'>
33
+ <div
34
+ class='
35
+ swiper-container overflow-hidden flex-1 pr-8 lg:pr-0 -mx-4 lg:mx-0 flex flex-col
36
+ lg:flex-col-reverse
37
+ '
38
+ data-controller='carousel'
39
+ data-carousel-options-value='{ "slidesPerView": 1, "centeredSlides": false, "spaceBetween": 16, "grabCursor": true, "breakpoints": { "768": { "slidesPerView": 3, "spaceBetween": 24 } }, "navigation": { "nextEl": ".swiper-custom-button-next-<%= section.id %>", "prevEl": ".swiper-custom-button-prev-<%= section.id %>" } }'
40
+ >
41
+ <div class='swiper-wrapper px-4 lg:px-0 h-auto'>
42
+ <%= render partial: "spree/posts/post",
43
+ collection: section.posts,
44
+ cached: spree_base_cache_scope,
45
+ as: :post %>
46
+ </div>
47
+ <%= button_tag class: "absolute p-2 bg-white rounded-full z-10 border border-accent left-0 disabled:hidden hover:border-primary ml-2 lg:ml-0 swiper-custom-button-prev-#{section.id} block top-[100px]", aria: { label: "Previous posts" }, style: "transform: translate(-50%, -50%);" do %>
48
+ <%= render "spree/shared/icons/chevron" %>
49
+ <% end %>
50
+ <%= button_tag class: "absolute p-2 bg-white rounded-full z-10 border border-accent right-0 disabled:hidden hover:border-primary mr-2 lg:mr-0 swiper-custom-button-next-#{section.id} block top-[100px]", aria: { label: "Next posts" }, style: "transform: translate(50%, -50%);" do %>
51
+ <%= render "spree/shared/icons/chevron_right" %>
52
+ <% end %>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
@@ -89,7 +89,7 @@
89
89
  <% if presenter.product %>
90
90
  <div class="absolute flex" data-controller="copy-input">
91
91
  <div class="has-float-label flex flex-col max-w-[200px]">
92
- <%= text_field_tag "product-#{presenter.product.id}-share-link", spree.product_url(presenter.product, host: current_store.url), class: 'text-ellipsis text-input border-r-0 !rounded-r-none !rounded-l-md', readonly: true, type: 'text', onclick: 'this.select()', data: { copy_input_target: 'input' } %>
92
+ <%= text_field_tag "product-#{presenter.product.id}-share-link", spree.product_url(presenter.product, host: current_store.url_or_custom_domain), class: 'text-ellipsis text-input border-r-0 !rounded-r-none !rounded-l-md', readonly: true, type: 'text', onclick: 'this.select()', data: { copy_input_target: 'input' } %>
93
93
  <%= label_tag "product-#{presenter.product.id}-share-link", Spree.t(:link) %>
94
94
  </div>
95
95
  <button
@@ -5,7 +5,7 @@
5
5
  when 'medium' then 'text-lg lg:text-xl font-medium'
6
6
  when 'large' then 'text-xl lg:text-2xl font-medium'
7
7
  end %>
8
- <% if section.taxon&.image&.attached? && section.preferred_show_taxon_image %>
8
+ <% if section.taxon&.page_builder_image&.attached? && section.preferred_show_taxon_image %>
9
9
  <% desktop_slides_amount = 2.5 %>
10
10
  <% section_with_image = true %>
11
11
  <% arrows_on_top = false %>
@@ -47,7 +47,7 @@
47
47
  <% if section_with_image %>
48
48
  <div class='lg:col-span-5'>
49
49
  <%= link_to spree.nested_taxons_path(section.taxon), data: { turbo_frame: "_top" } do %>
50
- <%= spree_image_tag(section.taxon.image, height: 500, width: 500, class: 'h-full w-full object-cover object-center', loading: :lazy) %>
50
+ <%= spree_image_tag(section.taxon.page_builder_image, height: 500, width: 500, class: 'h-full w-full object-cover object-center', loading: :lazy) %>
51
51
  <% end %>
52
52
  </div>
53
53
  <% end %>
@@ -12,9 +12,9 @@
12
12
  <div class="gap-6 grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 xl:gap-x-8 mb-7 hidden md:grid">
13
13
  <% section.links.each do |link| %>
14
14
  <%= page_builder_link_to link, title: link.label, class: 'group block overflow-hidden', target: link.open_in_new_tab.presence && '_blank' do %>
15
- <% if link.linkable.image&.attached? && link.linkable.image&.variable? %>
15
+ <% if link.linkable.page_builder_image&.attached? && link.linkable.page_builder_image&.variable? %>
16
16
  <div class="flex space-y-2 flex-col">
17
- <%= spree_image_tag(link.linkable.image, height: 300, width: 300, class: 'h-full w-full object-cover object-center group-hover:opacity-75 rounded-md bg-gray-200', loading: :lazy, alt: link.label) %>
17
+ <%= spree_image_tag(link.linkable.page_builder_image, height: 300, width: 300, class: 'h-full w-full object-cover object-center group-hover:opacity-75 rounded-md bg-gray-200', loading: :lazy, alt: link.label) %>
18
18
  <span><%= link.label %></span>
19
19
  </div>
20
20
  <% else %>
@@ -47,10 +47,9 @@
47
47
  <% section.links.each do |link| %>
48
48
  <div class='swiper-slide w-[200px]'>
49
49
  <%= page_builder_link_to link, title: link.label, class: 'group block overflow-hidden', target: link.open_in_new_tab.presence && '_blank' do %>
50
- <% if link.linkable.image&.attached? && link.linkable.image&.variable? %>
50
+ <% if link.linkable.page_builder_image.attached? %>
51
51
  <div class="flex space-y-2 flex-col">
52
- <%= spree_image_tag(link.linkable.image, height: 200, width: 200, class: 'h-full w-full object-cover object-center group-hover:opacity-75 rounded-md bg-gray-200', loading: :lazy, alt: link.label) %>
53
- <span><%= link.label %></span>
52
+ <%= spree_image_tag(link.linkable.page_builder_image, height: 200, width: 200, class: 'h-full w-full object-cover object-center group-hover:opacity-75 rounded-md bg-gray-200', loading: :lazy, alt: link.label) %>
54
53
  </div>
55
54
  <% else %>
56
55
  <div class="aspect-1 w-full group-hover:bg-gray-100 bg-gray-200 flex items-center justify-center relative">
@@ -1,11 +1,15 @@
1
1
  <div class="page-container py-12">
2
2
  <h1 class="text-2xl tracking-tight text-center lg:text-left mb-3 uppercase">
3
- <%= params[:id].titleize %>
3
+ <%= Spree.t(params[:id]) %>
4
4
  </h1>
5
- <p class="mb-8 text-center lg:text-left">
6
- Last update: <%= @policy&.updated_at&.strftime('%d/%m/%Y') %>
7
- </p>
8
- <div class="mb-5">
9
- <%= @policy&.to_s %>
10
- </div>
5
+
6
+ <% if @policy.present? %>
7
+ <p class="mb-8 text-center lg:text-left">
8
+ <%= Spree.t("storefront.policies.last_update_at", date: l(@policy.updated_at.to_date)) %>
9
+ </p>
10
+
11
+ <div class="mb-5">
12
+ <%= @policy&.to_s %>
13
+ </div>
14
+ <% end %>
11
15
  </div>
@@ -1,13 +1,22 @@
1
- <div id="<%= dom_id(post) %>">
2
- <%= link_to spree.post_path(post), class: 'block hover:opacity-70 transition-opacity' do %>
3
- <div class="h-[200px] w-full bg-gray-100">
4
- <% if post.image.attached? && post.image.variable? %>
5
- <%= spree_image_tag(post.image, width: 400, height: 200, class: 'h-full w-full object-cover object-center', loading: :lazy, alt: post.title) %>
6
- <% end %>
7
- </div>
1
+ <div class="swiper-slide w-full">
2
+ <div id="<%= dom_id(post) %>">
3
+ <%= link_to spree.post_path(post), class: 'block hover:opacity-70 transition-opacity', data: { turbo_frame: '_top' } do %>
4
+ <div class="h-[200px] w-full bg-gray-100">
5
+ <% if post.image.attached? && post.image.variable? %>
6
+ <%= spree_image_tag(
7
+ post.image,
8
+ width: 400,
9
+ height: 200,
10
+ class: "h-full w-full object-cover object-center",
11
+ loading: :lazy,
12
+ alt: post.title,
13
+ ) %>
14
+ <% end %>
15
+ </div>
8
16
 
9
- <h1 class="uppercase text-lg font-medium mt-4"><%= post.title %></h1>
10
- <div class="mt-2 text-sm"><%= local_time(post.published_at, '%B %e, %Y') %></div>
11
- <div class="mt-4"><%= post.shortened_description %></div>
12
- <% end %>
17
+ <h1 class="uppercase text-lg font-medium mt-4"><%= post.title %></h1>
18
+ <div class="mt-2 text-sm"><%= local_time(post.published_at, "%B %e, %Y") %></div>
19
+ <div class="mt-4"><%= post.shortened_description %></div>
20
+ <% end %>
21
+ </div>
13
22
  </div>
@@ -21,9 +21,9 @@ variant_not_available = selected_variant.nil? ||
21
21
  },
22
22
  disabled: product.price_in(current_currency).zero? do %>
23
23
  <% if not_selected_options.size == 1 %>
24
- <span><%= Spree.t(:please_select, option: not_selected_options[0].presentation) %></span>
24
+ <span><%= Spree.t('storefront.variant_picker.please_choose', option_type: not_selected_options[0].presentation) %></span>
25
25
  <% elsif not_all_options_selected %>
26
- <span><%= Spree.t(:please_select_all_options) %></span>
26
+ <span><%= Spree.t('storefront.variant_picker.please_choose_all_options') %></span>
27
27
  <% elsif variant_not_available %>
28
28
  <span><%= Spree.t(:notify_me_when_available) %></span>
29
29
  <%= render 'spree/shared/icons/bell' %>
@@ -43,9 +43,9 @@ variant_not_available = selected_variant.nil? ||
43
43
  },
44
44
  disabled: product.price_in(current_currency).zero? do %>
45
45
  <% if not_selected_options.size == 1 %>
46
- <span><%= Spree.t(:please_select, option: not_selected_options[0].presentation) %></span>
46
+ <span><%= Spree.t('storefront.variant_picker.please_choose', option_type: not_selected_options[0].presentation) %></span>
47
47
  <% elsif not_all_options_selected %>
48
- <span><%= Spree.t(:please_select_all_options) %></span>
48
+ <span><%= Spree.t('storefront.variant_picker.please_choose_all_options') %></span>
49
49
  <% elsif variant_not_available %>
50
50
  <span><%= Spree.t(:notify_me_when_available) %></span>
51
51
  <%= render 'spree/shared/icons/bell' %>
@@ -39,7 +39,7 @@
39
39
  </div>
40
40
  <% end %>
41
41
 
42
- <% product.product_properties.joins(:property).merge(Spree::Property.available_on_front_end).sort_by_property_position.each do |product_property| %>
42
+ <% product_properties(product).each do |product_property| %>
43
43
  <div class="product-property py-4 border-b border-default">
44
44
 
45
45
  <%= link_to "#property_#{product_property.id}", class: 'text-sm uppercase tracking-widest inline-flex w-full justify-between !border-b-transparent', data: { action: 'accordion#toggle' } do %>
@@ -4,7 +4,7 @@
4
4
  "@context": "https://schema.org/",
5
5
  "@type": "Product",
6
6
  "name": <%= product.name.to_json.html_safe %>,
7
- "url": <%= spree.product_url(product).to_json.html_safe %>,
7
+ "url": <%= spree.product_url(product, host: current_store.url_or_custom_domain).to_json.html_safe %>,
8
8
  <% if product.featured_image %>
9
9
  "image": [
10
10
  <%= spree_image_url(product.featured_image, width: 630, height: 630).to_json.html_safe %>
@@ -6,5 +6,5 @@
6
6
  "availability": "http://schema.org/<%= variant.available? ? 'InStock' : 'OutOfStock' %>",
7
7
  "price": <%= variant.amount_in(current_currency).to_json.html_safe %>,
8
8
  "priceCurrency": <%= current_currency.to_json.html_safe %>,
9
- "url": <%= spree.product_url(product, variant_id: variant.id).to_json.html_safe %>
9
+ "url": <%= spree.product_url(product, variant_id: variant.id, host: current_store.url_or_custom_domain).to_json.html_safe %>
10
10
  }
@@ -85,8 +85,7 @@
85
85
  <div id='pinch-to-zoom' class='fixed top-0 left-0 p-4 bg-background z-50 flex justify-center items-center flex-col'>
86
86
  <div class='w-14 h-14'><%= render 'spree/shared/icons/pinch' %></div>
87
87
  <div class='text-sm uppercase pt-4 px-5 text-center !leading-tight'>
88
- Pinch to <br>
89
- zoom
88
+ <%= Spree.t("storefront.products.pinch_to_zoom_html") %>
90
89
  </div>
91
90
  </div>
92
91
  <% end %>
@@ -4,7 +4,7 @@
4
4
  data-accordion-close-others-value="false">
5
5
  <% availability_filter_opened = permitted_products_params.dig(:filter, :purchasable).present? || permitted_products_params.dig(:filter, :out_of_stock).present? %>
6
6
  <%= link_to "#availability_filter", class: "cursor-pointer uppercase flex items-center justify-between h-10 px-4 lg:px-10 text-sm tracking-widest focus:outline-none transition duration-150 ease-in-out #{'st-accordion__icon--opened' if availability_filter_opened}", data: { action: 'accordion#toggle:prevent' } do %>
7
- <%= Spree.t(:availability) %>
7
+ <%= Spree.t(:availability).capitalize %>
8
8
  <%= render 'spree/shared/icons/chevron_down' %>
9
9
  <% end %>
10
10
  <div class='st-accordion__content' data-accordion-id='availability_filter'>
@@ -16,15 +16,15 @@
16
16
  data-no-ui-slider-range-value="[<%= filter_price_range[:min].floor %>,<%= filter_price_range[:max].ceil %>]">
17
17
  <div class="flex justify-between gap-6 px-4 lg:px-10 lg:text-sm">
18
18
  <div class="relative w-1/2">
19
- <%= f.number_field filter_price_range[:min].floor, class: "pl-16 without-arrows w-full peer focus:border-primary focus:ring-primary", inputmode: "numeric", name: "filter[min_price]", data: { no_ui_slider_target: "minInput" }, id: "price_from", value: params.dig(:filter, :min_price).present? ? min_price_value.to_i : nil, placeholder: filter_price_range[:min].floor %>
19
+ <%= f.number_field filter_price_range[:min].floor, class: "pl-16 text-right without-arrows w-full peer focus:border-primary focus:ring-primary", inputmode: "numeric", name: "filter[min_price]", data: { no_ui_slider_target: "minInput" }, id: "price_from", value: params.dig(:filter, :min_price).present? ? min_price_value.to_i : nil, placeholder: filter_price_range[:min].floor %>
20
20
  <label class="absolute left-0 top-0 flex pl-3 items-center h-full text-input-text peer-placeholder-shown:opacity-50" for="price_from">
21
- from <%= currency_symbol(current_currency) %>
21
+ <%= Spree.t(:from) %> <%= currency_symbol(current_currency) %>
22
22
  </label>
23
23
  </div>
24
24
  <div class="relative w-1/2">
25
- <%= f.number_field filter_price_range[:max].ceil, class: "pl-[2.75rem] without-arrows w-full peer focus:border-primary focus:ring-primary", placeholder: filter_price_range[:max].ceil, inputmode: "numeric", name: "filter[max_price]", data: { no_ui_slider_target: "maxInput" }, id: "price_to", value: params.dig(:filter, :max_price).present? ? max_price_value.to_i : nil %>
25
+ <%= f.number_field filter_price_range[:max].ceil, class: "pl-[2.75rem] text-right without-arrows w-full peer focus:border-primary focus:ring-primary", placeholder: filter_price_range[:max].ceil, inputmode: "numeric", name: "filter[max_price]", data: { no_ui_slider_target: "maxInput" }, id: "price_to", value: params.dig(:filter, :max_price).present? ? max_price_value.to_i : nil %>
26
26
  <label class="absolute left-0 top-0 flex pl-3 items-center h-full text-input-text peer-placeholder-shown:opacity-50" for="price_to">
27
- to <%= currency_symbol(current_currency) %>
27
+ <%= Spree.t(:to) %> <%= currency_symbol(current_currency) %>
28
28
  </label>
29
29
  </div>
30
30
  </div>
@@ -1,4 +1,6 @@
1
- <%= turbo_frame_tag "cart-icon-#{current_order&.item_count}", target: '_top' do %>
1
+ <% item_count ||= current_order&.item_count %>
2
+
3
+ <%= turbo_frame_tag "cart-icon-#{item_count}", target: '_top' do %>
2
4
  <%= link_to spree.cart_path,
3
5
  class: 'relative block w-6',
4
6
  id: "cart-pane-link",
@@ -6,7 +8,7 @@
6
8
  onclick: 'event.preventDefault()' do %>
7
9
  <%= render 'spree/shared/icons/cart' %>
8
10
  <span class='cart-counter w-full text-[8px] font-extrabold absolute top-[10px] text-center'>
9
- <%= current_order.item_count if current_order&.item_count&.positive? %>
11
+ <%= item_count if item_count&.positive? %>
10
12
  </span>
11
13
  <span class='sr-only'><%= Spree.t('storefront.cart.items_in_cart') %>, <%= Spree.t('storefront.cart.view_bag') %></span>
12
14
  <% end %>
@@ -1,3 +1,6 @@
1
+ <% order ||= current_order %>
2
+ <% item_count ||= order&.item_count %>
3
+
1
4
  <!-- begin sidebar/slideover -->
2
5
  <div
3
6
  id="cart-pane"
@@ -25,13 +28,13 @@
25
28
  <span class='relative block w-6'>
26
29
  <%= render 'spree/shared/icons/cart' %>
27
30
  <span class='cart-counter w-full text-[8px] font-extrabold absolute top-[10px] text-center'>
28
- <%= current_order.item_count if current_order.present? && current_order.item_count.to_i > 0 %>
31
+ <%= item_count if item_count&.positive? %>
29
32
  </span>
30
33
  <span class='sr-only'><%= Spree.t('storefront.cart.items_in_cart') %>, <%= Spree.t('storefront.cart.view_bag') %></span>
31
34
  </span>
32
35
  </div>
33
36
  <div class='flex-1 h-0 overflow-y-auto'>
34
- <%= turbo_frame_tag cart_id(current_order), class: 'cart-contents', src: spree.cart_path, data: { turbo_permanent: true } %>
37
+ <%= turbo_frame_tag cart_id(order), class: 'cart-contents', src: spree.cart_path, data: { turbo_permanent: true } %>
35
38
  </div>
36
39
  </div>
37
40
  </div>
@@ -32,9 +32,9 @@
32
32
  <meta property="twitter:image" content="<%= image_url %>" />
33
33
  <% end %>
34
34
 
35
- <% if @product && @product.price_in(current_currency).present? %>
35
+ <% if @product.present? && @product.price_in(current_currency).present? %>
36
36
  <meta property="og:price:amount" content="<%= @product.price_in(current_currency).amount.to_s %>">
37
- <meta property="og:price:currency" content="<%= current_order&.currency || current_store.default_currency %>">
37
+ <meta property="og:price:currency" content="<%= current_currency %>">
38
38
  <% end %>
39
39
 
40
40
  <% if current_store.twitter.present? %>
@@ -20,6 +20,7 @@ en:
20
20
  checkout:
21
21
  all_transactions_are_secure_and_encrypted: All transactions are secure and encrypted
22
22
  already_have_an_account: Already have an account?
23
+ backorder_notice: 'Some products in your cart will be dispatched a bit later than the rest of your order:'
23
24
  by_placing_this_order_you_agree_to: By placing this order you agree to
24
25
  calculated_at_next_step: Calculated at next step
25
26
  continue_to_cart: Continue to cart
@@ -30,11 +31,13 @@ en:
30
31
  one: This item will be removed from your cart because there are no delivery methods available for your address.
31
32
  other: These %{count} items will be removed from your cart because there are no delivery methods available for your address.
32
33
  gift_card_amount_applied: Gift card %{code} applied %{amount} to your order.
34
+ it_seems_you_already_have_an_account_html: It seems you already have an account with us. Please %{link} to continue.
33
35
  or_continue_below: or continue below
34
36
  order_already_paid: You don't need to pay anything, just click Place now button to confirm the order.
35
37
  order_success: Your order is confirmed!
36
38
  order_success_message: When your order is ready, you will receive an email confirmation.
37
39
  payment_processing_message: You will receive an email confirmation when your payment is processed.
40
+ return_to_cart: Return to cart
38
41
  shipping_not_available: Shipping not available
39
42
  signup_for_an_account: Create an account for faster future purchases, order tracking, and more.
40
43
  store_credits_amount_applied: You applied a %{amount} store credit to your order.
@@ -50,6 +53,10 @@ en:
50
53
  description: Take control of your settings and tailor your experience according to your preferences. Customize your notifications to suit your needs.
51
54
  join: Email me about new products, sales, and more. You can unsubscribe at any time.
52
55
  status: You are currently %{status} to the newsletters.
56
+ policies:
57
+ last_update_at: Last update %{date}
58
+ products:
59
+ pinch_to_zoom_html: Pinch to<br>zoom
53
60
  refund_action_not_required_message:
54
61
  order_canceled:
55
62
  fully: This order has been canceled. No further action is required. You will receive a refund within couple business days.
@@ -66,6 +73,7 @@ en:
66
73
  partially: This order has been partially refunded. The amount paid by the selected payment method will be refunded within couple business days. Please reach out to %{customer_support_email} to receive new voucher.
67
74
  variant_picker:
68
75
  please_choose: Please choose %{option_type}
76
+ please_choose_all_options: Please choose all options
69
77
  wished_items:
70
78
  add: Add to wishlist
71
79
  no_wished_items:
@@ -8,10 +8,97 @@ module Spree
8
8
  }
9
9
  end
10
10
 
11
- def custom_page_sections
12
- # you can override this method in your theme to return a list of custom page sections for your theme
13
- # [Spree::PageSections::Custom, Spree::PageSections::Custom2]
14
- []
11
+ # COLORS
12
+ # main colors
13
+ preference :primary_color, :string, default: '#000000'
14
+ preference :accent_color, :string, default: '#F0EFE9'
15
+ preference :danger_color, :string, default: '#C73528'
16
+ preference :neutral_color, :string, default: '#999999'
17
+ preference :background_color, :string, default: '#FFFFFF'
18
+ preference :text_color, :string, default: '#000000'
19
+ preference :success_color, :string, default: '#00C773'
20
+
21
+ # buttons
22
+ preference :button_background_color, :string
23
+ preference :button_text_color, :string, default: '#ffffff'
24
+ preference :button_hover_background_color, :string
25
+ preference :button_hover_text_color, :string
26
+ preference :button_border_color, :string
27
+
28
+ # borders
29
+ preference :border_color, :string, default: '#E9E7DC'
30
+ preference :sidebar_border_color, :string
31
+
32
+ preference :secondary_button_background_color, :string
33
+ preference :secondary_button_text_color, :string
34
+ preference :secondary_button_hover_background_color, :string
35
+ preference :secondary_button_hover_text_color, :string
36
+
37
+ # inputs
38
+ preference :input_text_color, :string, default: '#6b7280'
39
+ preference :input_background_color, :string, default: '#ffffff'
40
+ preference :input_border_color, :string
41
+ preference :input_focus_border_color, :string
42
+ preference :input_focus_background_color, :string
43
+ preference :input_focus_text_color, :string
44
+
45
+ # sidebar (checkout)
46
+ preference :checkout_sidebar_background_color, :string, default: '#f3f4f6'
47
+ preference :checkout_divider_background_color, :string
48
+ preference :checkout_sidebar_text_color, :string
49
+
50
+ # TYPOGRAPHY
51
+ preference :custom_font_code, :string, default: nil
52
+ # body
53
+ preference :font_family, :string, default: 'Inter'
54
+ preference :font_size_scale, :integer, default: 100
55
+ # headers
56
+ preference :header_font_family, :string, default: 'Inter'
57
+ preference :header_font_size_scale, :integer, default: 100
58
+ preference :headings_uppercase, :boolean, default: true
59
+
60
+ # BUTTONS
61
+ preference :button_border_thickness, :integer, default: 1
62
+ preference :button_border_opacity, :integer, default: 100
63
+ preference :button_border_radius, :integer, default: 100
64
+ preference :button_shadow_opacity, :integer, default: 0
65
+ preference :button_shadow_horizontal_offset, :integer, default: 0
66
+ preference :button_shadow_vertical_offset, :integer, default: 4
67
+ preference :button_shadow_blur, :integer, default: 5
68
+
69
+ # INPUTS
70
+ preference :input_border_thickness, :integer, default: 1
71
+ preference :input_border_opacity, :integer, default: 100
72
+ preference :input_border_radius, :integer, default: 8
73
+ preference :input_shadow_opacity, :integer, default: 0
74
+ preference :input_shadow_horizontal_offset, :integer, default: 0
75
+ preference :input_shadow_vertical_offset, :integer, default: 4
76
+ preference :input_shadow_blur, :integer, default: 5
77
+
78
+ # BORDERS
79
+ preference :border_width, :integer, default: 1
80
+ preference :border_radius, :integer, default: 6
81
+ preference :border_shadow_opacity, :integer, default: 0
82
+ preference :border_shadow_horizontal_offset, :integer, default: 0
83
+ preference :border_shadow_vertical_offset, :integer, default: 4
84
+ preference :border_shadow_blur, :integer, default: 5
85
+
86
+ # PRODUCT IMAGES
87
+ preference :product_listing_image_height, :integer, default: 300
88
+ preference :product_listing_image_width, :integer, default: 300
89
+ preference :product_listing_image_height_mobile, :integer, default: 190
90
+ preference :product_listing_image_width_mobile, :integer, default: 190
91
+
92
+ # Returns an array of available layout section classes for the theme, eg. header, footer, newsletter, etc.
93
+ #
94
+ # @return [Array<Class>]
95
+ def available_layout_sections
96
+ [
97
+ Spree::PageSections::AnnouncementBar,
98
+ Spree::PageSections::Header,
99
+ Spree::PageSections::Newsletter,
100
+ Spree::PageSections::Footer
101
+ ]
15
102
  end
16
103
  end
17
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_storefront
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.4
4
+ version: 5.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-22 00:00:00.000000000 Z
11
+ date: 2025-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.4
19
+ version: 5.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 5.0.4
26
+ version: 5.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: active_link_to
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -392,6 +392,7 @@ files:
392
392
  - app/views/themes/default/spree/orders/show.html.erb
393
393
  - app/views/themes/default/spree/page_sections/_announcement_bar.html.erb
394
394
  - app/views/themes/default/spree/page_sections/_custom_code.html.erb
395
+ - app/views/themes/default/spree/page_sections/_featured_posts.html.erb
395
396
  - app/views/themes/default/spree/page_sections/_featured_product.html.erb
396
397
  - app/views/themes/default/spree/page_sections/_featured_taxon.html.erb
397
398
  - app/views/themes/default/spree/page_sections/_featured_taxons.html.erb
@@ -542,9 +543,9 @@ licenses:
542
543
  - AGPL-3.0-or-later
543
544
  metadata:
544
545
  bug_tracker_uri: https://github.com/spree/spree/issues
545
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.0.4
546
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.0.5
546
547
  documentation_uri: https://docs.spreecommerce.org/
547
- source_code_uri: https://github.com/spree/spree/tree/v5.0.4
548
+ source_code_uri: https://github.com/spree/spree/tree/v5.0.5
548
549
  post_install_message:
549
550
  rdoc_options: []
550
551
  require_paths: