spree_storefront 5.1.0.beta3 → 5.1.0.rc1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +7 -1
  3. data/app/controllers/spree/account/gift_cards_controller.rb +15 -0
  4. data/app/controllers/spree/checkout_controller.rb +12 -6
  5. data/app/controllers/spree/line_items_controller.rb +14 -7
  6. data/app/controllers/spree/products_controller.rb +1 -1
  7. data/app/controllers/spree/search_controller.rb +1 -1
  8. data/app/controllers/spree/store_controller.rb +19 -17
  9. data/app/helpers/spree/cart_helper.rb +1 -1
  10. data/app/helpers/spree/checkout_helper.rb +1 -2
  11. data/app/helpers/spree/filters_helper.rb +34 -22
  12. data/app/helpers/spree/products_helper.rb +5 -1
  13. data/app/helpers/spree/storefront_helper.rb +6 -3
  14. data/app/javascript/spree/storefront/controllers/card_validation_controller.js +2 -0
  15. data/app/javascript/spree/storefront/controllers/cart_controller.js +5 -0
  16. data/app/views/devise/passwords/edit.html.erb +1 -1
  17. data/app/views/devise/registrations/new.html.erb +1 -1
  18. data/app/views/devise/shared/_links.html.erb +3 -3
  19. data/app/views/spree/addresses/edit.html.erb +2 -2
  20. data/app/views/spree/checkout/_address.html.erb +25 -38
  21. data/app/views/spree/checkout/_address_list_item.html.erb +14 -0
  22. data/app/views/spree/checkout/_coupon_code.html.erb +3 -3
  23. data/app/views/spree/checkout/_delivery.html.erb +3 -36
  24. data/app/views/spree/checkout/_delivery_backorder_notice.html.erb +10 -0
  25. data/app/views/spree/checkout/_delivery_shipping_rate.html.erb +22 -0
  26. data/app/views/spree/checkout/_line_item.html.erb +1 -1
  27. data/app/views/spree/checkout/_missing_all_line_items.html.erb +2 -2
  28. data/app/views/spree/checkout/_order_lock_version.html.erb +3 -0
  29. data/app/views/spree/checkout/_payment.html.erb +11 -9
  30. data/app/views/spree/checkout/_payment_methods.html.erb +1 -1
  31. data/app/views/spree/checkout/_store_credit.html.erb +1 -1
  32. data/app/views/spree/checkout/_summary.html.erb +45 -44
  33. data/app/views/spree/checkout/payment/_gateway.html.erb +12 -12
  34. data/app/views/spree/checkout/payment/_store_credit.html.erb +2 -2
  35. data/app/views/spree/checkout/update.turbo_stream.erb +1 -3
  36. data/app/views/spree/line_items/destroy.turbo_stream.erb +14 -10
  37. data/app/views/spree/seo/sitemap.xml.erb +2 -2
  38. data/app/views/themes/default/spree/account/_order.html.erb +5 -5
  39. data/app/views/themes/default/spree/account/gift_cards/_gift_card.html.erb +26 -0
  40. data/app/views/themes/default/spree/account/gift_cards/index.html.erb +30 -0
  41. data/app/views/themes/default/spree/checkout/complete.html.erb +1 -1
  42. data/app/views/themes/default/spree/orders/_line_item.html.erb +3 -3
  43. data/app/views/themes/default/spree/page_sections/_featured_posts.html.erb +56 -0
  44. data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +1 -1
  45. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +2 -2
  46. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +4 -5
  47. data/app/views/themes/default/spree/policies/show.html.erb +11 -7
  48. data/app/views/themes/default/spree/posts/_post.html.erb +20 -11
  49. data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +4 -4
  50. data/app/views/themes/default/spree/products/_details.html.erb +1 -1
  51. data/app/views/themes/default/spree/products/_json_ld.html.erb +1 -1
  52. data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +1 -1
  53. data/app/views/themes/default/spree/products/_media_gallery.html.erb +1 -2
  54. data/app/views/themes/default/spree/products/filters/_availability.html.erb +1 -1
  55. data/app/views/themes/default/spree/products/filters/_price.html.erb +4 -4
  56. data/app/views/themes/default/spree/products/filters/_taxons.erb +1 -1
  57. data/app/views/themes/default/spree/shared/_cart_icon.html.erb +4 -2
  58. data/app/views/themes/default/spree/shared/_cart_pane.html.erb +5 -2
  59. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +2 -2
  60. data/app/views/themes/default/spree/shared/_order_shipment.html.erb +11 -12
  61. data/app/views/themes/default/spree/shared/icons/_discord.html.erb +9 -0
  62. data/config/locales/en.yml +10 -1
  63. data/config/routes.rb +1 -0
  64. data/lib/generators/spree/storefront/theme/templates/model.rb.tt +91 -4
  65. data/lib/spree/storefront/testing_support/cart_utils.rb +30 -0
  66. metadata +16 -6
@@ -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>
@@ -24,9 +24,9 @@ variant_not_available = selected_variant.nil? ||
24
24
  },
25
25
  disabled: product.price_in(current_currency).zero? do %>
26
26
  <% if not_selected_options.size == 1 %>
27
- <span><%= Spree.t(:please_select, option: not_selected_options[0].presentation) %></span>
27
+ <span><%= Spree.t('storefront.variant_picker.please_choose', option_type: not_selected_options[0].presentation) %></span>
28
28
  <% elsif not_all_options_selected %>
29
- <span><%= Spree.t(:please_select_all_options) %></span>
29
+ <span><%= Spree.t('storefront.variant_picker.please_choose_all_options') %></span>
30
30
  <% elsif variant_not_available %>
31
31
  <span><%= Spree.t(:notify_me_when_available) %></span>
32
32
  <%= render 'spree/shared/icons/bell' %>
@@ -49,9 +49,9 @@ variant_not_available = selected_variant.nil? ||
49
49
  },
50
50
  disabled: product.price_in(current_currency).zero? do %>
51
51
  <% if not_selected_options.size == 1 %>
52
- <span><%= Spree.t(:please_select, option: not_selected_options[0].presentation) %></span>
52
+ <span><%= Spree.t('storefront.variant_picker.please_choose', option_type: not_selected_options[0].presentation) %></span>
53
53
  <% elsif not_all_options_selected %>
54
- <span><%= Spree.t(:please_select_all_options) %></span>
54
+ <span><%= Spree.t('storefront.variant_picker.please_choose_all_options') %></span>
55
55
  <% elsif variant_not_available %>
56
56
  <span><%= Spree.t(:notify_me_when_available) %></span>
57
57
  <%= 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>
@@ -6,7 +6,7 @@
6
6
  data-controller='accordion'
7
7
  data-accordion-close-others-value="false">
8
8
  <%= link_to "#taxonomy_filter_#{taxonomy.id}", 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 params[:filter].nil? || current_taxon.present? || permitted_products_params.dig(:filter, :taxonomy_ids, taxonomy.id.to_s, :taxon_ids).present?}", data: { action: 'accordion#toggle:prevent' } do %>
9
- <%= taxonomy.name.singularize %>
9
+ <%= taxonomy.name %>
10
10
  <%= render 'spree/shared/icons/chevron_down' %>
11
11
  <% end %>
12
12
  <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? %>
@@ -1,15 +1,17 @@
1
1
  <li class="border border-accent mb-4">
2
2
  <div class="p-4 lg:p-6">
3
3
  <div class="flex flex-col lg:flex-row lg:gap-6 gap-4">
4
- <div class="text-sm lg:w-1/2">
5
- <div class="tracking-widest uppercase mb-1">
6
- <%= Spree.t(:delivery_address) %>
7
- </div>
8
- <div class="!leading-[1.375rem] text-neutral-800">
9
- <%= render "spree/shared/address",
10
- address: shipment.address || shipment.order.ship_address %>
4
+ <% if shipment.order.requires_ship_address? %>
5
+ <div class="text-sm lg:w-1/2">
6
+ <div class="tracking-widest uppercase mb-1">
7
+ <%= Spree.t(:delivery_address) %>
8
+ </div>
9
+ <div class="!leading-[1.375rem] text-neutral-800">
10
+ <%= render "spree/shared/address",
11
+ address: shipment.address || shipment.order.ship_address %>
12
+ </div>
11
13
  </div>
12
- </div>
14
+ <% end %>
13
15
  <div class="text-sm lg:w-1/2 lg:flex justify-between">
14
16
  <div>
15
17
  <div class="tracking-widest uppercase mb-1">
@@ -31,10 +33,7 @@
31
33
  <% unless shipment.digital? %>
32
34
  <div class="mt-4 lg:-mt-2 lg:-mr-2">
33
35
  <% if shipment.shipped? && shipment.tracked? && shipment.tracking_url.present? %>
34
- <%= link_to Spree.t(:track_items),
35
- shipment.tracking_url,
36
- class: "!px-3 !py-1 block btn-primary !leading-6 text-sm text-center",
37
- target: :_blank %>
36
+ <%= shipment_tracking_link_to(shipment: shipment, name: Spree.t(:track_items), html_options: { class: "!px-3 !py-1 block btn-primary !leading-6 text-sm text-center", target: :_blank }) %>
38
37
  <% else %>
39
38
  <button
40
39
  class="
@@ -0,0 +1,9 @@
1
+ <svg
2
+ xmlns='http://www.w3.org/2000/svg'
3
+ width='16'
4
+ height='16'
5
+ viewBox='0 0 16 16'
6
+ fill='currentColor'
7
+ >
8
+ <path d="M18.942 5.556a16.299 16.299 0 0 0-4.126-1.297c-.178.321-.385.754-.529 1.097a15.175 15.175 0 0 0-4.573 0 11.583 11.583 0 0 0-.535-1.097 16.274 16.274 0 0 0-4.129 1.3c-2.611 3.946-3.319 7.794-2.965 11.587a16.494 16.494 0 0 0 5.061 2.593 12.65 12.65 0 0 0 1.084-1.785 10.689 10.689 0 0 1-1.707-.831c.143-.106.283-.217.418-.331 3.291 1.539 6.866 1.539 10.118 0 .137.114.277.225.418.331-.541.326-1.114.606-1.71.832a12.52 12.52 0 0 0 1.084 1.785 16.46 16.46 0 0 0 5.064-2.595c.415-4.396-.709-8.209-2.973-11.589zM8.678 14.813c-.988 0-1.798-.922-1.798-2.045s.793-2.047 1.798-2.047 1.815.922 1.798 2.047c.001 1.123-.793 2.045-1.798 2.045zm6.644 0c-.988 0-1.798-.922-1.798-2.045s.793-2.047 1.798-2.047 1.815.922 1.798 2.047c0 1.123-.793 2.045-1.798 2.045z"/>
9
+ </svg>
@@ -7,6 +7,7 @@ en:
7
7
  newsletter_settings: Newsletter settings
8
8
  no_addresses_description: If you place an order, you will find address details here.
9
9
  no_addresses_title: You currently have no Addresses
10
+ no_gift_cards: You currently have no gift cards
10
11
  no_orders_description: If you place an order, you will find details here.
11
12
  no_orders_title: You currently have no orders
12
13
  no_store_credits: You don't have any store credit.
@@ -20,6 +21,7 @@ en:
20
21
  checkout:
21
22
  all_transactions_are_secure_and_encrypted: All transactions are secure and encrypted
22
23
  already_have_an_account: Already have an account?
24
+ backorder_notice: 'Some products in your cart will be dispatched a bit later than the rest of your order:'
23
25
  by_placing_this_order_you_agree_to: By placing this order you agree to
24
26
  calculated_at_next_step: Calculated at next step
25
27
  continue_to_cart: Continue to cart
@@ -29,12 +31,14 @@ en:
29
31
  invalid_line_items:
30
32
  one: This item will be removed from your cart because there are no delivery methods available for your address.
31
33
  other: These %{count} items will be removed from your cart because there are no delivery methods available for your address.
32
- gift_card_amount_applied: Gift card %{code} applied %{amount} to your order.
34
+ gift_card_amount_applied: Gift Card %{code} applied %{amount} to your order.
35
+ it_seems_you_already_have_an_account_html: It seems you already have an account with us. Please %{link} to continue.
33
36
  or_continue_below: or continue below
34
37
  order_already_paid: You don't need to pay anything, just click Place now button to confirm the order.
35
38
  order_success: Your order is confirmed!
36
39
  order_success_message: When your order is ready, you will receive an email confirmation.
37
40
  payment_processing_message: You will receive an email confirmation when your payment is processed.
41
+ return_to_cart: Return to cart
38
42
  shipping_not_available: Shipping not available
39
43
  signup_for_an_account: Create an account for faster future purchases, order tracking, and more.
40
44
  special_instructions_placeholder: Here you can add any special instructions for your order
@@ -51,6 +55,10 @@ en:
51
55
  description: Take control of your settings and tailor your experience according to your preferences. Customize your notifications to suit your needs.
52
56
  join: Email me about new products, sales, and more. You can unsubscribe at any time.
53
57
  status: You are currently %{status} to the newsletters.
58
+ policies:
59
+ last_update_at: Last update %{date}
60
+ products:
61
+ pinch_to_zoom_html: Pinch to<br>zoom
54
62
  refund_action_not_required_message:
55
63
  order_canceled:
56
64
  fully: This order has been canceled. No further action is required. You will receive a refund within couple business days.
@@ -67,6 +75,7 @@ en:
67
75
  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.
68
76
  variant_picker:
69
77
  please_choose: Please choose %{option_type}
78
+ please_choose_all_options: Please choose all options
70
79
  wished_items:
71
80
  add: Add to wishlist
72
81
  no_wished_items:
data/config/routes.rb CHANGED
@@ -62,6 +62,7 @@ Spree::Core::Engine.add_routes do
62
62
  end
63
63
  resource :newsletter, only: [:edit, :update], controller: :newsletter
64
64
  resources :store_credits, only: [:index]
65
+ resources :gift_cards, only: [:index]
65
66
  end
66
67
 
67
68
  # Wishlists
@@ -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
@@ -0,0 +1,30 @@
1
+ module Spree
2
+ module Storefront
3
+ module TestingSupport
4
+ module CartUtils
5
+ def add_to_cart(product, goto_checkout = false)
6
+ visit spree.product_path(product)
7
+
8
+ click_button Spree.t(:add_to_cart)
9
+ wait_for_turbo
10
+ expect(page).to have_link('Checkout')
11
+
12
+ def view_cart
13
+ visit spree.cart_path
14
+ end
15
+
16
+ def click_checkout
17
+ click_link 'Checkout'
18
+ expect(page).to have_content('Contact information').and have_content('Shipping Address')
19
+ end
20
+
21
+ if block_given?
22
+ yield
23
+ else
24
+ goto_checkout ? click_checkout : view_cart
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ 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.1.0.beta3
4
+ version: 5.1.0.rc1
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-29 00:00:00.000000000 Z
11
+ date: 2025-07-02 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.1.0.beta3
19
+ version: 5.1.0.rc1
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.1.0.beta3
26
+ version: 5.1.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: active_link_to
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -209,6 +209,7 @@ files:
209
209
  - app/controllers/concerns/spree/theme_concern.rb
210
210
  - app/controllers/spree/account/addresses_controller.rb
211
211
  - app/controllers/spree/account/base_controller.rb
212
+ - app/controllers/spree/account/gift_cards_controller.rb
212
213
  - app/controllers/spree/account/newsletter_controller.rb
213
214
  - app/controllers/spree/account/orders_controller.rb
214
215
  - app/controllers/spree/account/profile_controller.rb
@@ -306,14 +307,18 @@ files:
306
307
  - app/views/spree/addresses/edit.html.erb
307
308
  - app/views/spree/addresses/new.html.erb
308
309
  - app/views/spree/checkout/_address.html.erb
310
+ - app/views/spree/checkout/_address_list_item.html.erb
309
311
  - app/views/spree/checkout/_button_processing.html.erb
310
312
  - app/views/spree/checkout/_coupon_code.html.erb
311
313
  - app/views/spree/checkout/_credit_card.html.erb
312
314
  - app/views/spree/checkout/_delivery.html.erb
315
+ - app/views/spree/checkout/_delivery_backorder_notice.html.erb
316
+ - app/views/spree/checkout/_delivery_shipping_rate.html.erb
313
317
  - app/views/spree/checkout/_line_item.html.erb
314
318
  - app/views/spree/checkout/_line_items.html.erb
315
319
  - app/views/spree/checkout/_missing_all_line_items.html.erb
316
320
  - app/views/spree/checkout/_missing_line_items.html.erb
321
+ - app/views/spree/checkout/_order_lock_version.html.erb
317
322
  - app/views/spree/checkout/_payment.html.erb
318
323
  - app/views/spree/checkout/_payment_methods.html.erb
319
324
  - app/views/spree/checkout/_payment_sources.html.erb
@@ -376,6 +381,8 @@ files:
376
381
  - app/views/themes/default/spree/account/addresses/_edit_address_modal.html.erb
377
382
  - app/views/themes/default/spree/account/addresses/_new_address_modal.html.erb
378
383
  - app/views/themes/default/spree/account/addresses/index.html.erb
384
+ - app/views/themes/default/spree/account/gift_cards/_gift_card.html.erb
385
+ - app/views/themes/default/spree/account/gift_cards/index.html.erb
379
386
  - app/views/themes/default/spree/account/newsletter/_newsletter_settings.html.erb
380
387
  - app/views/themes/default/spree/account/newsletter/edit.html.erb
381
388
  - app/views/themes/default/spree/account/newsletter/update.html.erb
@@ -396,6 +403,7 @@ files:
396
403
  - app/views/themes/default/spree/orders/show.html.erb
397
404
  - app/views/themes/default/spree/page_sections/_announcement_bar.html.erb
398
405
  - app/views/themes/default/spree/page_sections/_custom_code.html.erb
406
+ - app/views/themes/default/spree/page_sections/_featured_posts.html.erb
399
407
  - app/views/themes/default/spree/page_sections/_featured_product.html.erb
400
408
  - app/views/themes/default/spree/page_sections/_featured_taxon.html.erb
401
409
  - app/views/themes/default/spree/page_sections/_featured_taxons.html.erb
@@ -489,6 +497,7 @@ files:
489
497
  - app/views/themes/default/spree/shared/icons/_delete.html.erb
490
498
  - app/views/themes/default/spree/shared/icons/_delivery.html.erb
491
499
  - app/views/themes/default/spree/shared/icons/_disabled.html.erb
500
+ - app/views/themes/default/spree/shared/icons/_discord.html.erb
492
501
  - app/views/themes/default/spree/shared/icons/_edit.html.erb
493
502
  - app/views/themes/default/spree/shared/icons/_facebook.html.erb
494
503
  - app/views/themes/default/spree/shared/icons/_filter.html.erb
@@ -532,6 +541,7 @@ files:
532
541
  - lib/spree/storefront/configuration.rb
533
542
  - lib/spree/storefront/engine.rb
534
543
  - lib/spree/storefront/testing_support/capybara_utils.rb
544
+ - lib/spree/storefront/testing_support/cart_utils.rb
535
545
  - lib/spree_storefront.rb
536
546
  - vendor/colornames.json
537
547
  - vendor/javascript/@kanety--stimulus-accordion.js
@@ -550,9 +560,9 @@ licenses:
550
560
  - AGPL-3.0-or-later
551
561
  metadata:
552
562
  bug_tracker_uri: https://github.com/spree/spree/issues
553
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.0.beta3
563
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.1.0.rc1
554
564
  documentation_uri: https://docs.spreecommerce.org/
555
- source_code_uri: https://github.com/spree/spree/tree/v5.1.0.beta3
565
+ source_code_uri: https://github.com/spree/spree/tree/v5.1.0.rc1
556
566
  post_install_message:
557
567
  rdoc_options: []
558
568
  require_paths: