spree_storefront 5.1.8 → 5.2.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/spree/account/newsletter_controller.rb +2 -0
  3. data/app/controllers/spree/errors_controller.rb +21 -0
  4. data/app/controllers/spree/newsletter_subscribers_controller.rb +27 -13
  5. data/app/controllers/spree/policies_controller.rb +2 -20
  6. data/app/controllers/spree/store_controller.rb +2 -2
  7. data/app/helpers/spree/page_helper.rb +38 -2
  8. data/app/helpers/spree/payment_methods_helper.rb +7 -0
  9. data/app/helpers/spree/storefront_helper.rb +18 -0
  10. data/app/helpers/spree/theme_helper.rb +10 -2
  11. data/app/helpers/spree/turbo_helper.rb +2 -1
  12. data/app/javascript/spree/storefront/application.js +1 -0
  13. data/app/javascript/spree/storefront/controllers/prefetch_lazy_controller.js +26 -0
  14. data/app/javascript/spree/storefront/controllers/toggle_menu_controller.js +0 -1
  15. data/app/views/layouts/spree/storefront.html.erb +5 -14
  16. data/app/views/spree/checkout/_footer.html.erb +14 -9
  17. data/app/views/spree/checkout/_line_items.html.erb +2 -2
  18. data/app/views/spree/checkout/_missing_line_items.html.erb +1 -1
  19. data/app/views/spree/checkout/_payment_method.html.erb +15 -0
  20. data/app/views/spree/checkout/_payment_methods.html.erb +1 -18
  21. data/app/views/spree/checkout/_summary.html.erb +3 -3
  22. data/app/views/spree/checkout/payment/_gateway.html.erb +3 -3
  23. data/app/views/spree/errors/403.html.erb +7 -0
  24. data/app/views/spree/errors/403.json.erb +1 -0
  25. data/app/views/spree/errors/404.html.erb +7 -0
  26. data/app/views/spree/errors/404.json.erb +1 -0
  27. data/app/views/spree/errors/422.html.erb +7 -0
  28. data/app/views/spree/errors/422.json.erb +1 -0
  29. data/app/views/spree/errors/500.html.erb +7 -0
  30. data/app/views/spree/errors/500.json.erb +1 -0
  31. data/app/views/spree/errors/503.html.erb +7 -0
  32. data/app/views/spree/errors/503.json.erb +1 -0
  33. data/app/views/spree/home/index.html.erb +3 -1
  34. data/app/views/spree/newsletter_subscribers/create.turbo_stream.erb +1 -1
  35. data/app/views/themes/default/spree/account/_orders.html.erb +1 -1
  36. data/app/views/themes/default/spree/account/addresses/index.html.erb +1 -1
  37. data/app/views/themes/default/spree/account/gift_cards/index.html.erb +1 -1
  38. data/app/views/themes/default/spree/account/store_credits/index.html.erb +1 -1
  39. data/app/views/themes/default/spree/metafields/_boolean.html.erb +5 -0
  40. data/app/views/themes/default/spree/metafields/_json.html.erb +3 -0
  41. data/app/views/themes/default/spree/metafields/_long_text.html.erb +1 -0
  42. data/app/views/themes/default/spree/metafields/_number.html.erb +1 -0
  43. data/app/views/themes/default/spree/metafields/_rich_text.html.erb +1 -0
  44. data/app/views/themes/default/spree/metafields/_short_text.html.erb +1 -0
  45. data/app/views/themes/default/spree/orders/_cart.html.erb +1 -1
  46. data/app/views/themes/default/spree/orders/_line_item.html.erb +1 -1
  47. data/app/views/themes/default/spree/page_sections/_announcement_bar.html.erb +1 -1
  48. data/app/views/themes/default/spree/page_sections/_breadcrumbs.html.erb +18 -0
  49. data/app/views/themes/default/spree/page_sections/_custom_code.html.erb +1 -1
  50. data/app/views/themes/default/spree/page_sections/_featured_posts.html.erb +1 -1
  51. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +1 -1
  52. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +1 -1
  53. data/app/views/themes/default/spree/page_sections/_footer.html.erb +2 -2
  54. data/app/views/themes/default/spree/page_sections/_header.html.erb +140 -139
  55. data/app/views/themes/default/spree/page_sections/_image_banner.html.erb +5 -4
  56. data/app/views/themes/default/spree/page_sections/_image_with_text.html.erb +3 -2
  57. data/app/views/themes/default/spree/page_sections/_newsletter.html.erb +43 -39
  58. data/app/views/themes/default/spree/page_sections/_page_title.html.erb +1 -1
  59. data/app/views/themes/default/spree/page_sections/_product_details.html.erb +47 -66
  60. data/app/views/themes/default/spree/page_sections/_rich_text.html.erb +1 -1
  61. data/app/views/themes/default/spree/page_sections/_taxon_banner.html.erb +1 -1
  62. data/app/views/themes/default/spree/page_sections/_taxon_grid.html.erb +1 -1
  63. data/app/views/themes/default/spree/page_sections/_video.html.erb +1 -1
  64. data/app/views/themes/default/spree/page_sections/nav/_desktop.html.erb +1 -1
  65. data/app/views/themes/default/spree/page_sections/nav/_mobile.html.erb +4 -9
  66. data/app/views/themes/default/spree/policies/show.html.erb +8 -9
  67. data/app/views/themes/default/spree/products/_add_to_waitlist.html.erb +3 -3
  68. data/app/views/themes/default/spree/products/_breadcrumbs.html.erb +1 -1
  69. data/app/views/themes/default/spree/products/_color_swatches.html.erb +2 -2
  70. data/app/views/themes/default/spree/products/_description.html.erb +11 -0
  71. data/app/views/themes/default/spree/products/_details.html.erb +2 -2
  72. data/app/views/themes/default/spree/products/_featured_image.html.erb +2 -8
  73. data/app/views/themes/default/spree/products/_media_gallery.html.erb +1 -1
  74. data/app/views/themes/default/spree/products/_metafields.html.erb +18 -0
  75. data/app/views/themes/default/spree/products/_quantity_selector.html.erb +1 -2
  76. data/app/views/themes/default/spree/settings/show.html.erb +2 -2
  77. data/app/views/themes/default/spree/shared/_address.html.erb +1 -1
  78. data/app/views/themes/default/spree/shared/_css_variables.html.erb +1 -1
  79. data/app/views/themes/default/spree/shared/_json_ld.html.erb +1 -1
  80. data/app/views/themes/default/spree/shared/_logo.html.erb +2 -9
  81. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +6 -2
  82. data/app/views/themes/default/spree/shared/_order_details.html.erb +2 -2
  83. data/app/views/themes/default/spree/shared/_order_shipment.html.erb +1 -1
  84. data/app/views/themes/default/spree/wishlists/show.html.erb +1 -1
  85. data/config/initializers/assets.rb +3 -1
  86. data/config/locales/en.yml +5 -2
  87. data/config/routes.rb +9 -1
  88. data/lib/generators/spree/storefront/install/install_generator.rb +2 -1
  89. data/lib/generators/spree/storefront/install/templates/{application.tailwind.css → application.css} +105 -14
  90. data/lib/generators/spree/storefront/install/templates/tailwind.config.js +3 -114
  91. data/lib/spree/storefront/configuration.rb +3 -0
  92. data/lib/spree/storefront/engine.rb +5 -3
  93. data/lib/spree/storefront.rb +1 -3
  94. metadata +43 -34
@@ -12,35 +12,11 @@
12
12
  <template data-product-form-target="spinnerTemplate">
13
13
  <%= render "spree/shared/icons/spinner" %>
14
14
  </template>
15
- <%= render 'spree/products/breadcrumbs', product: product, taxons: product_breadcrumb_taxons(product) %>
15
+
16
16
  <div id="product-details-page" class="grid grid-cols-1 lg:grid-cols-12 gap-x-14">
17
- <div class="lg:hidden">
18
- <% if product.brand %>
19
- <%= link_to spree.nested_taxons_path(product.brand), title: product.brand_name do %>
20
- <h3 class="text-sm lg:mt-0 inline-block mb-1">
21
- <%= product.brand_name %>
22
- </h3>
23
- <% end %>
24
- <% end %>
25
- <h1 class="text-2xl uppercase tracking-tight mb-4 font-medium">
26
- <%= product.name %>
27
- </h1>
28
- <%= link_to spree.product_path(product), class: "text-2xl uppercase tracking-tight font-medium hidden" do %>
29
- <%= product.name %>
30
- <% end %>
31
- <%=
32
- render 'spree/products/price',
33
- product: product,
34
- use_variant: true,
35
- selected_variant: @selected_variant,
36
- price_class: "my-4 lg:text-lg lg:font-medium",
37
- price_container_class: "w-full"
38
- %>
39
- </div>
17
+ <% images = product_media_gallery_images(product, selected_variant: @selected_variant, variant_from_options: @variant_from_options) %>
40
18
 
41
19
  <div class="lg:col-span-7 relative">
42
- <% images = product_media_gallery_images(product, selected_variant: @selected_variant, variant_from_options: @variant_from_options) %>
43
-
44
20
  <div class="lg:hidden mb-6">
45
21
  <%= render 'spree/products/media_gallery', images: images, product: product %>
46
22
  </div>
@@ -50,53 +26,58 @@
50
26
  </div>
51
27
 
52
28
  <div class="lg:col-span-5 lg:col-start-8">
53
- <div data-controller='sticky-button' data-product-form-target="productDetails">
54
- <div class="hidden lg:block">
55
- <% if product.brand %>
56
- <%= link_to spree.nested_taxons_path(product.brand), title: product.brand_name do %>
57
- <h3 class="text-sm mt-3 lg:mt-0 inline-block uppercase">
58
- <%= product.brand_name %>
59
- </h3>
60
- <% end %>
61
- <% end %>
62
- <h1 class="text-2xl uppercase tracking-tight mb-4 mt-2 font-medium">
63
- <%= product.name %>
64
- </h1>
29
+ <% show_waitlist_modal = spree.respond_to?(:waitlists_path) && current_variant.present? %>
30
+ <div
31
+ <% if show_waitlist_modal %>
32
+ data-controller="modal"
33
+ <% end %>
34
+ data-modal-allow-background-close="true"
35
+ class="h-full w-full waitlist-modal"
36
+ data-modal-backdrop-color-value="rgba(0,0,0,0.32)">
37
+ <%= form_with(url: spree.line_items_path, method: :post, data: { controller: "turbo-stream-form", product_form_target: "form" }) do |f| %>
38
+ <%= hidden_field_tag :variant_id, current_variant&.id %>
65
39
 
66
- <%=
67
- render 'spree/products/price',
68
- product: product,
69
- use_variant: true,
70
- selected_variant: @selected_variant,
71
- price_class: "my-4 lg:text-lg lg:font-medium"
72
- %>
73
- </div>
74
- <%= render 'spree/products/tags', product: product %>
75
- <% show_waitlist_modal = spree.respond_to?(:waitlists_path) && current_variant.present? %>
76
- <div
77
- <% if show_waitlist_modal %>
78
- data-controller="modal"
79
- <% end %>
80
- data-modal-allow-background-close="true"
81
- class="h-full w-full waitlist-modal"
82
- data-modal-backdrop-color-value="rgba(0,0,0,0.32)">
83
- <%= form_with(url: spree.line_items_path, method: :post, data: { controller: "turbo-stream-form", product_form_target: "form" }) do |f| %>
84
- <%= render 'spree/products/variant_picker', product: product, selected_variant: @selected_variant %>
85
- <%= render 'spree/products/quantity_selector', product: product, selected_variant: @selected_variant %>
86
- <div class="flex w-full my-5">
87
- <%= render 'spree/products/add_to_cart_button', product: product, selected_variant: @selected_variant, sticky_button_classes: "w-full" %>
88
- <%= render 'spree/products/add_to_wishlist', variant: current_variant, css_classes: 'btn-secondary ml-5 h-12 !py-0 !px-3 border-default', icon_size: 24 %>
89
- </div>
40
+ <div data-product-form-target="productDetails">
41
+ <% section.blocks.each do |block| %>
42
+ <div <%= block_attributes(block) %>>
43
+ <% case block.class.name %>
44
+ <% when 'Spree::PageBlocks::Products::Title' %>
45
+ <h1 class="text-2xl uppercase tracking-tight font-medium">
46
+ <%= product.name %>
47
+ </h1>
48
+ <% when 'Spree::PageBlocks::Products::Brand' %>
49
+ <% if product.brand %>
50
+ <%= link_to spree.nested_taxons_path(product.brand), title: product.brand_name do %>
51
+ <h3 class="text-sm lg:mt-0 inline-block mb-1">
52
+ <%= product.brand_name %>
53
+ </h3>
54
+ <% end %>
55
+ <% end %>
56
+ <% when 'Spree::PageBlocks::Products::Price' %>
57
+ <%= render 'spree/products/price', product: product, use_variant: true, selected_variant: @selected_variant, price_class: "lg:text-lg lg:font-medium", price_container_class: "w-full" %>
58
+ <% when 'Spree::PageBlocks::Products::VariantPicker' %>
59
+ <%= render 'spree/products/variant_picker', product: product, selected_variant: @selected_variant %>
60
+ <% when 'Spree::PageBlocks::Products::QuantitySelector' %>
61
+ <%= render 'spree/products/quantity_selector', product: product, selected_variant: @selected_variant %>
62
+ <% when 'Spree::PageBlocks::Products::BuyButtons' %>
63
+ <div class="flex w-full" data-controller='sticky-button'>
64
+ <%= render 'spree/products/add_to_cart_button', product: product, selected_variant: @selected_variant, sticky_button_classes: "w-full" %>
65
+ <%= render 'spree/products/add_to_wishlist', variant: current_variant, css_classes: 'btn-secondary ml-5 h-12 !py-0 !px-3 border-default', icon_size: 24 %>
66
+ </div>
67
+ <% when 'Spree::PageBlocks::Products::Description' %>
68
+ <%= render 'spree/products/description', product: product, block: block, section: section %>
69
+ <% when 'Spree::PageBlocks::Metafields' %>
70
+ <%= render 'spree/products/metafields', product: product, block: block, section: section %>
71
+ <% end %>
72
+ </div>
90
73
  <% end %>
91
- <%= render 'spree/products/add_to_waitlist', variant: current_variant if show_waitlist_modal %>
92
- </div>
74
+ <% end %>
93
75
 
94
- <%= render 'spree/products/details', product: product %>
76
+ <%= render 'spree/products/add_to_waitlist', variant: current_variant if show_waitlist_modal %>
95
77
  </div>
96
78
  </div>
97
79
  </div>
98
80
  </div>
99
81
  </div>
100
-
101
82
  <%= render 'spree/products/json_ld', product: product, selected_variant: @selected_variant %>
102
83
  </turbo-frame>
@@ -1,4 +1,4 @@
1
- <% cache_unless page_builder_enabled?, spree_base_cache_scope.call(section) do %>
1
+ <% cache_unless page_builder_enabled?, spree_storefront_base_cache_scope.call(section) do %>
2
2
  <div style="<%= section_styles(section) %>">
3
3
  <div class="page-container rich-text">
4
4
  <% section.blocks.each do |block| %>
@@ -1,4 +1,4 @@
1
- <% cache_unless page_builder_enabled?, [*spree_base_cache_scope.call(section), taxon].compact do %>
1
+ <% cache_unless page_builder_enabled?, [*spree_storefront_base_cache_scope.call(section), taxon].compact do %>
2
2
  <div
3
3
  style="<%= section_styles(section) %>"
4
4
  id="taxon-banner-<%= taxon.id %>"
@@ -1,4 +1,4 @@
1
- <% cache_unless page_builder_enabled?, [*spree_base_cache_scope.call(section), @taxons].compact do %>
1
+ <% cache_unless page_builder_enabled?, [*spree_storefront_base_cache_scope.call(section), @taxons].compact do %>
2
2
  <div style='<%= section_styles(section) %>'>
3
3
  <h1 class='text-xl lg:text-2xl font-medium pb-8 page-container' style='<%= section_heading_styles(section) %>'>
4
4
  <%= section.heading %>
@@ -1,4 +1,4 @@
1
- <% cache_unless page_builder_enabled?, spree_base_cache_scope.call(section) do %>
1
+ <% cache_unless page_builder_enabled?, spree_storefront_base_cache_scope.call(section) do %>
2
2
  <% separated_vertically = section.preferred_separated == 'vertically' %>
3
3
 
4
4
  <div style="<%= section_styles(section) %>">
@@ -31,7 +31,7 @@
31
31
  </div>
32
32
  <% end %>
33
33
  <% if block.try(:featured_taxon) %>
34
- <% cache spree_base_cache_scope.call(block.featured_taxon) do %>
34
+ <% cache spree_storefront_base_cache_scope.call(block.featured_taxon) do %>
35
35
  <% if block.featured_taxon.image.attached? && block.featured_taxon.image.variable? %>
36
36
  <%= link_to spree_storefront_resource_url(block.featured_taxon), class: "flex flex-col col-start-4" do %>
37
37
  <%= spree_image_tag(block.featured_taxon.image, width: 360, height: 360, class: 'w-full h-auto aspect-1', loading: :lazy, alt: block.featured_taxon.name) %>
@@ -1,4 +1,4 @@
1
- <div class="bg-background mt-4 border-default border-t overflow-x-hidden h-full w-screen overflow-y-hidden">
1
+ <div class="bg-background border-default border-t overflow-x-hidden h-full w-screen overflow-y-hidden">
2
2
  <div class="h-full flex transform has-[.currency-and-locale-modal:not(.hidden)]:transform-none relative transition-transform duration-300" data-controller="mobile-nav">
3
3
  <div class="w-screen shrink-0 flex flex-col h-full flex-grow-0">
4
4
  <div class="flex-grow overflow-y-scroll">
@@ -21,7 +21,7 @@
21
21
  </button>
22
22
  <div class="p-4 pt-0 w-full gap-2 flex flex-col">
23
23
  <% if block.try(:featured_taxon) %>
24
- <% cache spree_base_cache_scope.call(block.featured_taxon) do %>
24
+ <% cache spree_storefront_base_cache_scope.call(block.featured_taxon) do %>
25
25
  <% if block.featured_taxon.image.attached? && block.featured_taxon.image.variable? %>
26
26
  <%= link_to spree_storefront_resource_url(block.featured_taxon), class: "flex w-full pt-4" do %>
27
27
  <%= spree_image_tag(block.featured_taxon.image, width: 140, height: 140, class: 'h-auto aspect-1 w-2/5 max-w-[140px]', loading: :lazy, alt: block.featured_taxon.name) %>
@@ -103,12 +103,7 @@
103
103
 
104
104
  <% if should_render_currency_dropdown? || should_render_locale_dropdown? %>
105
105
  <div class="flex mt-4 justify-end">
106
- <div
107
- data-controller="modal"
108
- data-modal-allow-background-close="true"
109
- data-modal-
110
- class=""
111
- data-modal-backdrop-color-value="rgba(0,0,0,0.32)">
106
+ <div data-controller="modal" data-modal-disable-backdrop="true">
112
107
  <%= button_tag class: 'flex gap-2 items-center', data: {action: 'modal#open'} do %>
113
108
  <% if should_render_currency_dropdown? %>
114
109
  <span>
@@ -123,7 +118,7 @@
123
118
  </span>
124
119
  <% end %>
125
120
  <% end %>
126
- <%= turbo_frame_tag :settings_modal, src: spree.settings_path, loading: :lazy %>
121
+ <%= turbo_frame_tag :settings_modal, src: spree.settings_path, loading: :lazy %>
127
122
  </div>
128
123
  </div>
129
124
  <% end %>
@@ -1,15 +1,14 @@
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
- <%= Spree.t(params[:id]) %>
3
+ <%= @policy.name %>
4
4
  </h1>
5
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>
6
+ <p class="mb-8 text-center lg:text-left">
7
+ <%= Spree.t(:updated_at) %>:
8
+ <%= l(@policy.updated_at.to_date) %>
9
+ </p>
10
10
 
11
- <div class="mb-5">
12
- <%= @policy&.to_s %>
13
- </div>
14
- <% end %>
11
+ <div class="mb-5">
12
+ <%= @policy.body.to_s %>
13
+ </div>
15
14
  </div>
@@ -3,7 +3,7 @@
3
3
  data-action="waitlist:created@window->modal#close click->modal#closeBackground keyup@window->modal#closeWithKeyboard"
4
4
  class="hidden animate-fadeIn fixed inset-0 overflow-y-auto flex items-end md:items-center justify-center z-[9999] h-dvh w-full"
5
5
  style="animation-duration: 150ms;">
6
- <div class="w-full lg:w-[600px] relative h-auto lg:max-h-screen flex justify-center flex-col gap-4 bg-background p-5 ">
6
+ <div class="w-full lg:w-[600px] relative h-auto lg:max-h-screen flex justify-center flex-col gap-4 bg-background p-5 border border-default">
7
7
  <button
8
8
  type="button"
9
9
  data-waitlist-close-button
@@ -21,8 +21,8 @@
21
21
  </div>
22
22
  <%= form_for :waitlist, url: spree.waitlists_path, method: :post, class: "flex w-full gap-4 flex-col", data: { product_form_target: 'addToWaitlistForm', controller: 'turbo-stream-form enable-button' } do |f| %>
23
23
  <div class="w-full">
24
- <%= f.hidden_field :variant_id, value: variant.id %>
25
- <%= f.email_field :email, value: try_spree_current_user&.email, class: 'w-full', required: true, placeholder: Spree.t(:email), data: { enable_button_target: 'input' } %>
24
+ <%= f.hidden_field :variant_id, value: variant&.id %>
25
+ <%= f.email_field :email, value: try_spree_current_user&.email, class: 'w-full', required: true, placeholder: Spree.t(:email), data: { enable_button_target: 'input' }, autofocus: true %>
26
26
  </div>
27
27
  <div class="flex flex-col gap-2">
28
28
  <label class="flex items-center gap-2 cursor-pointer group text-sm">
@@ -1,6 +1,6 @@
1
1
  <nav id="breadcrumbs" aria-label="breadcrumbs">
2
2
  <!-- desktop -->
3
- <ul class="hidden md:inline-flex space-x-3 mb-4 lg:mb-5 text-sm">
3
+ <ul class="hidden md:inline-flex gap-3 mb-4 lg:mb-5 text-sm">
4
4
  <% taxons.each_with_index do |taxon, index| %>
5
5
  <li class="opacity-50"><%= link_to taxon.name, spree.nested_taxons_path(taxon), title: taxon.name %></li>
6
6
  <div class="breadcrumb-square opacity-50"></div>
@@ -2,7 +2,7 @@
2
2
  <% variants_with_color = product.variants.find_all { |variant| variant.option_values.find { |ov| ov.option_type_id == color_option.id } } if color_option.present? %>
3
3
 
4
4
  <% if color_option.present? && variants_with_color.length > 0 %>
5
- <% cache spree_base_cache_scope.call(variants_with_color) do %>
5
+ <% cache spree_storefront_base_cache_scope.call(variants_with_color) do %>
6
6
  <% color_values = product.option_values.find_all { |ov| ov.option_type_id == color_option.id }.uniq %>
7
7
  <%= raw(Spree::ColorsPreviewStylesPresenter.new(color_values.map { |o| { name: o.presentation, filter_name: o.name } }).to_s) %>
8
8
 
@@ -11,7 +11,7 @@
11
11
  <% selected_variant = variants_with_color.find { |variant| variant.option_values.include?(color_value) } %>
12
12
  <% next if selected_variant.blank? %>
13
13
 
14
- <% cache spree_base_cache_scope.call(selected_variant) do %>
14
+ <% cache spree_storefront_base_cache_scope.call(selected_variant) do %>
15
15
  <div
16
16
  data-variant-id="<%= selected_variant.id %>"
17
17
  class="[&:nth-of-type(n+4)]:hidden [&:nth-of-type(n+4)]:md:block [&:nth-of-type(n+8)]:md:hidden cursor-pointer"
@@ -0,0 +1,11 @@
1
+ <% if product.storefront_description.present? %>
2
+ <% description_text = strip_tags(product.storefront_description) %>
3
+ <div data-controller="read-more" class="flex flex-col gap-4" data-read-more-more-text-value="<%= Spree.t(:read_more) %>" data-read-more-less-text-value="Read less">
4
+ <div class="prose product-description text-sm <%= 'product-description-truncated' if description_text.size > 250 %>" data-read-more-target="content">
5
+ <%= raw(product.storefront_description) %>
6
+ </div>
7
+ <% if description_text.size > 250 %>
8
+ <%= button_tag Spree.t(:read_more), type: 'button', data: { action: "read-more#toggle" }, class: "font-bold underline text-sm" %>
9
+ <% end %>
10
+ </div>
11
+ <% end %>
@@ -1,4 +1,4 @@
1
- <% cache spree_base_cache_scope.call(product) do %>
1
+ <% cache spree_storefront_base_cache_scope.call(product) do %>
2
2
  <% if product.storefront_description.present? %>
3
3
  <% description_text = strip_tags(product.storefront_description) %>
4
4
  <div data-controller="read-more" class="py-4 flex flex-col gap-4" data-read-more-more-text-value="<%= Spree.t(:read_more) %>" data-read-more-less-text-value="Read less">
@@ -6,7 +6,7 @@
6
6
  <%= raw(product.storefront_description) %>
7
7
  </div>
8
8
  <% if description_text.size > 250 %>
9
- <%= button_tag Spree.t(:read_more), data: { action: "read-more#toggle" }, class: "font-bold underline text-sm" %>
9
+ <%= button_tag Spree.t(:read_more), type: 'button', data: { action: "read-more#toggle" }, class: "font-bold underline text-sm" %>
10
10
  <% end %>
11
11
  </div>
12
12
  <% end %>
@@ -1,27 +1,21 @@
1
1
  <% with_cover_image ||= true %>
2
2
  <% object ||= product %>
3
-
4
3
  <% if object.default_image.present? && object.default_image.attached? %>
5
4
  <% height ||= theme_setting('product_listing_image_height') %>
6
5
  <% width ||= theme_setting('product_listing_image_width') %>
7
-
8
6
  <figure class="group <%= 'aspect-1' if height == width %> card-product-featured-images-container bg-transparent h-full">
9
7
  <% if with_cover_image %>
10
8
  <% object_class = 'object-cover object-center' %>
11
9
  <% else %>
12
10
  <% object_class = 'object-contain object-top' %>
13
11
  <% end %>
14
-
15
12
  <% image_hover_class = object.secondary_image.present? && object.secondary_image.attached? ?
16
13
  "w-full group-hover:opacity-0 transition-opacity duration-500 z-10 relative h-full bg-background product-card !max-h-full #{object_class}" :
17
14
  "w-full h-full !max-h-full #{object_class}" %>
18
-
19
- <%= spree_image_tag(object.default_image, width: width, height: height, loading: :lazy, alt: object.default_image.alt, class: image_hover_class) %>
20
-
15
+ <%= spree_image_tag(object.default_image, width: width, height: height, loading: :lazy, alt: "#{object.name} #{Spree.t('storefront.products.primary_image', default: 'primary image')}", class: image_hover_class) %>
21
16
  <% if object.secondary_image.present? && object.secondary_image.attached? %>
22
17
  <% secondary_image_class = "w-full absolute top-0 left-0 opacity-100 h-full !max-h-full #{object_class}" %>
23
-
24
- <%= spree_image_tag(object.secondary_image, width: width, height: height, loading: :lazy, alt: object.secondary_image.alt, class: secondary_image_class) %>
18
+ <%= spree_image_tag(object.secondary_image, width: width, height: height, loading: :lazy, alt: "#{object.name} #{Spree.t('storefront.products.secondary_image', default: 'secondary image')}", class: secondary_image_class) %>
25
19
  <% end %>
26
20
  </figure>
27
21
  <% else %>
@@ -1,6 +1,6 @@
1
1
  <% desktop ||= false %>
2
2
 
3
- <% cache [*spree_base_cache_scope.call(product), images, desktop].compact do %>
3
+ <% cache [*spree_storefront_base_cache_scope.call(product), images, desktop].compact do %>
4
4
  <% if desktop == true %>
5
5
  <div
6
6
  class="media-gallery w-full h-full media-gallery-desktop"
@@ -0,0 +1,18 @@
1
+ <div class="st-accordion" data-controller="accordion">
2
+ <% metafields_by_definition = @product.metafields.index_by { |m| m.metafield_definition.id.to_s } %>
3
+ <% block.preferred_metafield_definition_ids.each do |definition_id| %>
4
+ <% metafield = metafields_by_definition[definition_id.to_s] %>
5
+ <% next unless metafield %>
6
+ <% next unless metafield.metafield_definition.available_on_front_end? %>
7
+
8
+ <details class="product-metafield border-b border-default group" id="metafield_<%= metafield.id %>">
9
+ <summary class="text-sm uppercase tracking-widest inline-flex w-full justify-between items-center py-4 cursor-pointer focus:outline-none">
10
+ <span><%= metafield.name %></span>
11
+ <span class="ml-2 transition-transform group-open:rotate-180">
12
+ <%= render 'spree/shared/icons/chevron_down' %>
13
+ </span>
14
+ </summary>
15
+ <%= render "spree/metafields/#{metafield.type.demodulize.underscore}", metafield: metafield %>
16
+ </details>
17
+ <% end %>
18
+ </div>
@@ -1,5 +1,5 @@
1
1
  <% selected_variant ||= nil %>
2
- <p class="quantity-selector-label text-sm tracking-widest uppercase py-2"><%= Spree.t(:quantity) %></p>
2
+ <p class="quantity-selector-label text-sm tracking-widest uppercase pb-2"><%= Spree.t(:quantity) %></p>
3
3
  <div class="inline-block">
4
4
  <div class="quantity-picker" data-controller="quantity-picker">
5
5
  <%= button_tag class: 'decrease-quantity',
@@ -22,7 +22,6 @@
22
22
  <% end %>
23
23
  </div>
24
24
  </div>
25
- <%= hidden_field_tag :variant_id, selected_variant&.id %>
26
25
  <% if selected_variant && !selected_variant.backorderable? %>
27
26
  <% if selected_variant.total_on_hand.between?(1, 4) %>
28
27
  <p class="text-red-500 text-center text-sm mt-1" style="width: 117px">
@@ -2,9 +2,9 @@
2
2
  <div
3
3
  data-modal-target="container"
4
4
  data-action="click->modal#closeBackground keyup@window->modal#closeWithKeyboard"
5
- class="currency-and-locale-modal hidden animate-fadeIn fixed inset-0 overflow-y-auto flex items-end md:items-center justify-center z-[9999] h-dvh w-full"
5
+ class="currency-and-locale-modal hidden fixed inset-0 overflow-y-auto flex items-end md:items-start justify-center z-[9999] h-dvh w-full"
6
6
  style="animation-duration: 150ms;">
7
- <div class="w-full lg:w-[600px] relative h-auto lg:max-h-screen flex justify-center flex-col gap-4 bg-background p-5 ">
7
+ <div class="w-full lg:w-[600px] relative h-auto lg:max-h-screen flex justify-center flex-col gap-4 bg-background p-5 border border-default mt-12">
8
8
  <button
9
9
  type="button"
10
10
  data-action="modal#close"
@@ -1,4 +1,4 @@
1
- <% cache [*spree_base_cache_scope.call(address), address.user] do %>
1
+ <% cache [*spree_storefront_base_cache_scope.call(address), address.user] do %>
2
2
  <div class="text-sm">
3
3
  <div class="mb-1"><%= address.full_name %></div>
4
4
  <% unless address.company.blank? %>
@@ -1,4 +1,4 @@
1
- <% cache_unless page_builder_enabled?, spree_base_cache_scope.call(current_theme) do %>
1
+ <% cache_unless page_builder_enabled?, spree_storefront_base_cache_scope.call(current_theme) do %>
2
2
  <style data-turbo-track="reload">
3
3
  <%= theme_setting(:custom_font_css_import) if theme_setting(:custom_font_css_import).present? %>
4
4
 
@@ -1,4 +1,4 @@
1
- <% cache spree_base_cache_scope.call(current_store) do %>
1
+ <% cache spree_storefront_base_cache_scope.call(current_store) do %>
2
2
  <script type="application/ld+json">
3
3
  {
4
4
  "@context": "https://schema.org",
@@ -1,13 +1,10 @@
1
1
  <% logo ||= current_store.logo %>
2
2
  <% height ||= 64 %>
3
3
  <% logo_css ||= '' %>
4
-
5
4
  <%= link_to spree.root_path, id: 'site-logo' do %>
6
- <span class='sr-only'><%= current_store.name %></span>
7
5
  <% if logo.present? && logo.attached? && logo.variable? %>
8
6
  <% aspect_ratio = spree_asset_aspect_ratio(logo) %>
9
7
  <% logo_style = "aspect-ratio: #{aspect_ratio};" %>
10
-
11
8
  <% if aspect_ratio.to_f > 10 %>
12
9
  <% mobile_class = "h-[16px]" %>
13
10
  <% desktop_class = "md:h-[32px]" %>
@@ -20,7 +17,6 @@
20
17
  <% else %>
21
18
  <% mobile_class = "h-[32px]" %>
22
19
  <% end %>
23
-
24
20
  <% if defined?(height) && height > 0 %>
25
21
  <% logo_style += "--desktop-height: #{height}px;" %>
26
22
  <% cdn_height = height %>
@@ -30,13 +26,10 @@
30
26
  <% else %>
31
27
  <% cdn_height = 32 %>
32
28
  <% end %>
33
-
34
29
  <% img_class = "w-auto #{mobile_class} #{desktop_class} #{logo_css}" %>
35
-
36
30
  <% variant_options = spree_image_variant_options(resize_to_fit: [nil, cdn_height * 3]) %>
37
-
38
- <%= image_tag main_app.cdn_image_url(logo.variant(variant_options)), class: img_class, alt: current_store.name, style: logo_style, height: cdn_height %>
31
+ <%= image_tag main_app.cdn_image_url(logo.variant(variant_options)), class: img_class, alt: current_store.name + " logo", style: logo_style, height: cdn_height %>
39
32
  <% else %>
40
- <h1 class='text-lg uppercase text-center'><%= current_store.name %></h1>
33
+ <h1 class='text-lg text-center uppercase'><%= current_store.name %></h1>
41
34
  <% end %>
42
35
  <% end %>
@@ -32,8 +32,12 @@
32
32
  <meta property="twitter:image" content="<%= image_url %>" />
33
33
  <% end %>
34
34
 
35
- <% if @product.present? && @product.price_in(current_currency).present? %>
36
- <meta property="og:price:amount" content="<%= @product.price_in(current_currency).amount.to_s %>">
35
+ <% if @product.present? %>
36
+ <% cache [@product, current_currency] do %>
37
+ <% if @product.price_in(current_currency).present? %>
38
+ <meta property="og:price:amount" content="<%= @product.price_in(current_currency).amount.to_s %>">
39
+ <% end %>
40
+ <% end %>
37
41
  <meta property="og:price:currency" content="<%= current_currency %>">
38
42
  <% end %>
39
43
 
@@ -21,7 +21,7 @@
21
21
  <%== color_options_style_for_line_items(shipments.flat_map(&:line_items)) %>
22
22
 
23
23
  <ul>
24
- <%= render partial: 'spree/shared/order_shipment', collection: shipments, as: :shipment, cached: spree_base_cache_scope %>
24
+ <%= render partial: 'spree/shared/order_shipment', collection: shipments, as: :shipment, cached: spree_storefront_base_cache_scope %>
25
25
  </ul>
26
26
 
27
27
  <% if order.special_instructions.present? %>
@@ -55,7 +55,7 @@
55
55
  <%= Spree.t(:payment_information) %>
56
56
  </div>
57
57
  <div class="!leading-[1.375rem] text-neutral-800">
58
- <%= render collection: order.payments.valid, partial: 'spree/shared/payment', cached: spree_base_cache_scope %>
58
+ <%= render collection: order.payments.valid, partial: 'spree/shared/payment', cached: spree_storefront_base_cache_scope %>
59
59
  </div>
60
60
  </div>
61
61
  <% end %>
@@ -66,6 +66,6 @@
66
66
  <%= render partial: "spree/shared/order_line_item",
67
67
  collection: shipment.inventory_units,
68
68
  as: :inventory_unit,
69
- cached: spree_base_cache_scope %>
69
+ cached: spree_storefront_base_cache_scope %>
70
70
  </div>
71
71
  </li>
@@ -8,7 +8,7 @@
8
8
  </h1>
9
9
  <% if @wished_items.any? %>
10
10
  <div class="grid lg:grid-cols-3 gap-x-6 gap-y-10 lg:mb-24">
11
- <%= render collection: @wished_items, partial: 'spree/wishlists/wished_item', cached: ->(wished_item) { [*spree_base_cache_scope.call(wished_item), wished_item.variant, current_currency] } %>
11
+ <%= render collection: @wished_items, partial: 'spree/wishlists/wished_item', cached: ->(wished_item) { [*spree_storefront_base_cache_scope.call(wished_item), wished_item.variant, current_currency] } %>
12
12
  </div>
13
13
  <% else %>
14
14
  <%= render 'no_wished_items' %>
@@ -1 +1,3 @@
1
- Rails.application.config.assets.precompile << 'spree_storefront_manifest.js'
1
+ if Rails.application.config.respond_to?(:assets)
2
+ Rails.application.config.assets.precompile << 'spree_storefront_manifest.js'
3
+ end
@@ -50,15 +50,18 @@ en:
50
50
  message_not_sent: Unfortunately we weren't able to send the email at this time. Please try again later
51
51
  message_sent: Message sent!
52
52
  newsletter_subscribers:
53
+ already_subscribed: You are already subscribed to our newsletter
53
54
  success: Thank you for subscribing to our newsletter!
55
+ verification_failed: Verification failed
56
+ verified: Your email has been verified!
54
57
  newsletter_subscription:
55
58
  description: Take control of your settings and tailor your experience according to your preferences. Customize your notifications to suit your needs.
56
59
  join: Email me about new products, sales, and more. You can unsubscribe at any time.
57
60
  status: You are currently %{status} to the newsletters.
58
- policies:
59
- last_update_at: Last update %{date}
60
61
  products:
61
62
  pinch_to_zoom_html: Pinch to<br>zoom
63
+ primary_image: primary image
64
+ secondary_image: secondary image
62
65
  refund_action_not_required_message:
63
66
  order_canceled:
64
67
  fully: This order has been canceled. No further action is required. You will receive a refund within couple business days.
data/config/routes.rb CHANGED
@@ -75,7 +75,9 @@ Spree::Core::Engine.add_routes do
75
75
  resource :settings, only: [:update, :show]
76
76
 
77
77
  # Newsletter
78
- resources :newsletter_subscribers, only: [:create]
78
+ resources :newsletter_subscribers, only: [:create] do
79
+ get :verify, on: :collection
80
+ end
79
81
 
80
82
  # Contact form
81
83
  resources :contacts, only: [:new, :create]
@@ -87,6 +89,12 @@ Spree::Core::Engine.add_routes do
87
89
  root to: 'home#index'
88
90
  end
89
91
 
92
+ get '/forbidden', to: 'errors#show', code: 403, as: :forbidden
93
+ if Rails.env.test?
94
+ get '/errors', to: 'errors#show'
95
+ get '/errors/:path', to: 'errors#show', as: :pathed_errors
96
+ end
97
+
90
98
  get 'robots.txt' => 'seo#robots'
91
99
  get 'sitemap' => 'seo#sitemap'
92
100
  get 'sitemap.xml.gz' => 'seo#sitemap'
@@ -15,7 +15,8 @@ module Spree
15
15
  end
16
16
 
17
17
  def install
18
- template 'application.tailwind.css', 'app/assets/stylesheets/application.tailwind.css'
18
+ empty_directory Rails.root.join('app/assets/tailwind') if Rails.root && !Rails.root.join('app/assets/tailwind').exist?
19
+ template 'application.css', 'app/assets/tailwind/application.css'
19
20
  template 'tailwind.config.js', 'config/tailwind.config.js'
20
21
 
21
22
  if Rails.root && Rails.root.join("Procfile.dev").exist?