spree_storefront 5.0.4 → 5.0.6

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/spree/storefront/devise_concern.rb +48 -0
  3. data/app/controllers/spree/line_items_controller.rb +14 -7
  4. data/app/controllers/spree/products_controller.rb +1 -1
  5. data/app/controllers/spree/search_controller.rb +1 -1
  6. data/app/controllers/spree/store_controller.rb +17 -15
  7. data/app/helpers/spree/cart_helper.rb +1 -1
  8. data/app/helpers/spree/filters_helper.rb +5 -1
  9. data/app/helpers/spree/products_helper.rb +5 -1
  10. data/app/helpers/spree/storefront_helper.rb +10 -2
  11. data/app/javascript/spree/storefront/controllers/card_validation_controller.js +2 -0
  12. data/app/javascript/spree/storefront/controllers/cart_controller.js +5 -0
  13. data/app/views/devise/passwords/edit.html.erb +1 -1
  14. data/app/views/devise/registrations/new.html.erb +1 -1
  15. data/app/views/devise/shared/_links.html.erb +3 -3
  16. data/app/views/spree/addresses/edit.html.erb +2 -2
  17. data/app/views/spree/checkout/_address.html.erb +3 -4
  18. data/app/views/spree/checkout/_coupon_code.html.erb +1 -1
  19. data/app/views/spree/checkout/_delivery.html.erb +1 -2
  20. data/app/views/spree/checkout/_missing_all_line_items.html.erb +2 -2
  21. data/app/views/spree/checkout/_payment_methods.html.erb +1 -1
  22. data/app/views/spree/checkout/_summary.html.erb +45 -44
  23. data/app/views/spree/checkout/payment/_gateway.html.erb +12 -12
  24. data/app/views/spree/line_items/destroy.turbo_stream.erb +14 -8
  25. data/app/views/spree/seo/sitemap.xml.erb +2 -2
  26. data/app/views/themes/default/spree/account/_order.html.erb +5 -5
  27. data/app/views/themes/default/spree/checkout/complete.html.erb +1 -1
  28. data/app/views/themes/default/spree/orders/_line_item.html.erb +3 -3
  29. data/app/views/themes/default/spree/page_sections/_featured_posts.html.erb +56 -0
  30. data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +1 -1
  31. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +2 -2
  32. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +4 -5
  33. data/app/views/themes/default/spree/policies/show.html.erb +11 -7
  34. data/app/views/themes/default/spree/posts/_post.html.erb +20 -11
  35. data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +4 -4
  36. data/app/views/themes/default/spree/products/_details.html.erb +1 -1
  37. data/app/views/themes/default/spree/products/_json_ld.html.erb +1 -1
  38. data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +1 -1
  39. data/app/views/themes/default/spree/products/_media_gallery.html.erb +1 -2
  40. data/app/views/themes/default/spree/products/filters/_availability.html.erb +1 -1
  41. data/app/views/themes/default/spree/products/filters/_price.html.erb +4 -4
  42. data/app/views/themes/default/spree/shared/_account_pane.html.erb +1 -1
  43. data/app/views/themes/default/spree/shared/_cart_icon.html.erb +4 -2
  44. data/app/views/themes/default/spree/shared/_cart_pane.html.erb +6 -3
  45. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +2 -2
  46. data/config/locales/en.yml +8 -0
  47. data/lib/generators/spree/storefront/devise/devise_generator.rb +47 -0
  48. data/lib/generators/spree/storefront/devise/templates/user_passwords_controller.rb +17 -0
  49. data/lib/generators/spree/storefront/devise/templates/user_registrations_controller.rb +17 -0
  50. data/lib/generators/spree/storefront/devise/templates/user_sessions_controller.rb +17 -0
  51. data/lib/generators/spree/storefront/theme/templates/model.rb.tt +91 -4
  52. metadata +12 -6
@@ -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>
@@ -20,7 +20,7 @@
20
20
  >
21
21
  <%= render 'spree/shared/icons/cross' %>
22
22
  </button>
23
- <span class='text-xl font-medium uppercase leading-loose'><%= Spree.t(:account) %></span>
23
+ <span class='text-xl font-medium uppercase leading-none'><%= Spree.t(:account) %></span>
24
24
  <span></span>
25
25
  </div>
26
26
  <%= turbo_frame_tag "login", src: spree_login_path, loading: "lazy" %>
@@ -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"
@@ -21,17 +24,17 @@
21
24
  ) do %>
22
25
  <%= render 'spree/shared/icons/close' %>
23
26
  <% end %>
24
- <span class='text-xl font-medium uppercase leading-loose'><%= Spree.t(:cart) %></span>
27
+ <span class='text-xl font-medium uppercase leading-none'><%= Spree.t(:cart) %></span>
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:
@@ -0,0 +1,47 @@
1
+ require 'rails/generators'
2
+
3
+ module Spree
4
+ module Storefront
5
+ module Generators
6
+ class DeviseGenerator < Rails::Generators::Base
7
+ desc 'Installs Spree Storefront Devise controllers'
8
+
9
+ def self.source_paths
10
+ [
11
+ File.expand_path('templates', __dir__),
12
+ File.expand_path('../templates', "../#{__FILE__}"),
13
+ File.expand_path('../templates', "../../#{__FILE__}")
14
+ ]
15
+ end
16
+
17
+ def install
18
+ template 'user_sessions_controller.rb', 'app/controllers/spree/user_sessions_controller.rb'
19
+ template 'user_registrations_controller.rb', 'app/controllers/spree/user_registrations_controller.rb'
20
+ template 'user_passwords_controller.rb', 'app/controllers/spree/user_passwords_controller.rb'
21
+
22
+ # add devise routes
23
+ insert_into_file 'config/routes.rb', after: "Rails.application.routes.draw do\n" do
24
+ <<-ROUTES.strip_heredoc.indent!(2)
25
+ Spree::Core::Engine.add_routes do
26
+ # Storefront routes
27
+ scope '(:locale)', locale: /\#{Spree.available_locales.join('|')\}/, defaults: { locale: nil } do
28
+ devise_for(
29
+ Spree.user_class.model_name.singular_route_key,
30
+ class_name: Spree.user_class.to_s,
31
+ path: :user,
32
+ controllers: {
33
+ sessions: 'spree/user_sessions',
34
+ passwords: 'spree/user_passwords',
35
+ registrations: 'spree/user_registrations'
36
+ },
37
+ router_name: :spree
38
+ )
39
+ end
40
+ end
41
+ ROUTES
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class UserPasswordsController < ::Devise::PasswordsController
3
+ include Spree::Storefront::DeviseConcern
4
+
5
+ protected
6
+
7
+ def translation_scope
8
+ 'devise.user_passwords'
9
+ end
10
+
11
+ private
12
+
13
+ def title
14
+ Spree.t(:forgot_password)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class UserRegistrationsController < ::Devise::RegistrationsController
3
+ include Spree::Storefront::DeviseConcern
4
+
5
+ protected
6
+
7
+ def translation_scope
8
+ 'devise.user_registrations'
9
+ end
10
+
11
+ private
12
+
13
+ def title
14
+ Spree.t(:sign_up)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class UserSessionsController < ::Devise::SessionsController
3
+ include Spree::Storefront::DeviseConcern
4
+
5
+ protected
6
+
7
+ def translation_scope
8
+ 'devise.user_sessions'
9
+ end
10
+
11
+ private
12
+
13
+ def title
14
+ Spree.t(:login)
15
+ end
16
+ end
17
+ end