spree_storefront 5.0.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 (341) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +13 -0
  3. data/Rakefile +15 -0
  4. data/app/assets/config/spree_storefront_manifest.js +6 -0
  5. data/app/assets/stylesheets/storefront_page_builder.css +51 -0
  6. data/app/controllers/concerns/spree/cart_methods.rb +40 -0
  7. data/app/controllers/concerns/spree/locale_urls.rb +23 -0
  8. data/app/controllers/concerns/spree/password_protected.rb +17 -0
  9. data/app/controllers/concerns/spree/theme_concern.rb +29 -0
  10. data/app/controllers/spree/account/addresses_controller.rb +16 -0
  11. data/app/controllers/spree/account/base_controller.rb +20 -0
  12. data/app/controllers/spree/account/newsletter_controller.rb +34 -0
  13. data/app/controllers/spree/account/orders_controller.rb +34 -0
  14. data/app/controllers/spree/account/profile_controller.rb +23 -0
  15. data/app/controllers/spree/account/store_credits_controller.rb +23 -0
  16. data/app/controllers/spree/account/wished_items_controller.rb +45 -0
  17. data/app/controllers/spree/addresses_controller.rb +101 -0
  18. data/app/controllers/spree/checkout_controller.rb +365 -0
  19. data/app/controllers/spree/contacts_controller.rb +46 -0
  20. data/app/controllers/spree/digital_links_controller.rb +48 -0
  21. data/app/controllers/spree/home_controller.rb +5 -0
  22. data/app/controllers/spree/line_items_controller.rb +96 -0
  23. data/app/controllers/spree/newsletter_subscribers_controller.rb +43 -0
  24. data/app/controllers/spree/order_status_controller.rb +32 -0
  25. data/app/controllers/spree/orders_controller.rb +104 -0
  26. data/app/controllers/spree/page_sections_controller.rb +17 -0
  27. data/app/controllers/spree/pages_controller.rb +13 -0
  28. data/app/controllers/spree/password_controller.rb +21 -0
  29. data/app/controllers/spree/policies_controller.rb +17 -0
  30. data/app/controllers/spree/posts_controller.rb +76 -0
  31. data/app/controllers/spree/products_controller.rb +99 -0
  32. data/app/controllers/spree/search_controller.rb +39 -0
  33. data/app/controllers/spree/seo_controller.rb +25 -0
  34. data/app/controllers/spree/settings_controller.rb +68 -0
  35. data/app/controllers/spree/store_controller.rb +247 -0
  36. data/app/controllers/spree/taxonomies_controller.rb +30 -0
  37. data/app/controllers/spree/taxons_controller.rb +46 -0
  38. data/app/controllers/spree/wishlists_controller.rb +19 -0
  39. data/app/finders/spree/storefront/variant_finder.rb +80 -0
  40. data/app/helpers/spree/analytics_helper.rb +28 -0
  41. data/app/helpers/spree/cart_helper.rb +48 -0
  42. data/app/helpers/spree/checkout_analytics_helper.rb +77 -0
  43. data/app/helpers/spree/checkout_helper.rb +58 -0
  44. data/app/helpers/spree/filters_helper.rb +180 -0
  45. data/app/helpers/spree/fonts_helper.rb +58 -0
  46. data/app/helpers/spree/orders_helper.rb +7 -0
  47. data/app/helpers/spree/page_helper.rb +67 -0
  48. data/app/helpers/spree/posts_helper.rb +42 -0
  49. data/app/helpers/spree/products_helper.rb +205 -0
  50. data/app/helpers/spree/storefront_helper.rb +86 -0
  51. data/app/helpers/spree/storefront_locale_helper.rb +42 -0
  52. data/app/helpers/spree/theme_helper.rb +244 -0
  53. data/app/helpers/spree/turbo_helper.rb +13 -0
  54. data/app/helpers/spree/turbo_stream_actions_helper.rb +13 -0
  55. data/app/helpers/spree/wishlist_helper.rb +7 -0
  56. data/app/javascript/spree/storefront/application.js +156 -0
  57. data/app/javascript/spree/storefront/controllers/accordion_controller.js +25 -0
  58. data/app/javascript/spree/storefront/controllers/account_nav_controller.js +10 -0
  59. data/app/javascript/spree/storefront/controllers/card_validation_controller.js +103 -0
  60. data/app/javascript/spree/storefront/controllers/carousel_controller.js +44 -0
  61. data/app/javascript/spree/storefront/controllers/cart_controller.js +10 -0
  62. data/app/javascript/spree/storefront/controllers/checkout_address_book_controller.js +28 -0
  63. data/app/javascript/spree/storefront/controllers/checkout_delivery_controller.js +39 -0
  64. data/app/javascript/spree/storefront/controllers/checkout_promotions_controller.js +28 -0
  65. data/app/javascript/spree/storefront/controllers/checkout_summary_controller.js +46 -0
  66. data/app/javascript/spree/storefront/controllers/clear_input_controller.js +23 -0
  67. data/app/javascript/spree/storefront/controllers/copy_input_controller.js +19 -0
  68. data/app/javascript/spree/storefront/controllers/dropdown_controller.js +14 -0
  69. data/app/javascript/spree/storefront/controllers/header_controller.js +33 -0
  70. data/app/javascript/spree/storefront/controllers/infinite_scroll_controller.js +31 -0
  71. data/app/javascript/spree/storefront/controllers/lightbox_controller.js +138 -0
  72. data/app/javascript/spree/storefront/controllers/mobile_nav_controller.js +17 -0
  73. data/app/javascript/spree/storefront/controllers/modal_controller.js +15 -0
  74. data/app/javascript/spree/storefront/controllers/no_ui_slider_controller.js +55 -0
  75. data/app/javascript/spree/storefront/controllers/pdp_desktop_gallery_controller.js +28 -0
  76. data/app/javascript/spree/storefront/controllers/plp_variant_picker_controller.js +151 -0
  77. data/app/javascript/spree/storefront/controllers/product_form_controller.js +136 -0
  78. data/app/javascript/spree/storefront/controllers/quantity_picker_controller.js +43 -0
  79. data/app/javascript/spree/storefront/controllers/search_suggestions_controller.js +61 -0
  80. data/app/javascript/spree/storefront/controllers/searchable_list_controller.js +25 -0
  81. data/app/javascript/spree/storefront/controllers/slideover_controller.js +40 -0
  82. data/app/javascript/spree/storefront/controllers/sticky_button_controller.js +32 -0
  83. data/app/javascript/spree/storefront/controllers/toggle_menu_controller.js +32 -0
  84. data/app/javascript/spree/storefront/controllers/turbo_stream_form_controller.js +51 -0
  85. data/app/javascript/spree/storefront/controllers/wished_item_controller.js +69 -0
  86. data/app/javascript/spree/storefront/helpers/lazy_load_controllers_with_manifest.js +78 -0
  87. data/app/javascript/spree/storefront/helpers/show_flash_message.js +25 -0
  88. data/app/models/spree/color_names.rb +35 -0
  89. data/app/models/spree/contact.rb +24 -0
  90. data/app/presenters/spree/colors_preview_styles_presenter.rb +84 -0
  91. data/app/presenters/spree/featured_product_presenter.rb +42 -0
  92. data/app/presenters/spree/mega_nav_presenter.rb +55 -0
  93. data/app/views/devise/passwords/edit.html.erb +22 -0
  94. data/app/views/devise/passwords/new.html.erb +16 -0
  95. data/app/views/devise/registrations/_form.html.erb +21 -0
  96. data/app/views/devise/registrations/edit.html.erb +24 -0
  97. data/app/views/devise/registrations/new.html.erb +27 -0
  98. data/app/views/devise/sessions/new.html.erb +25 -0
  99. data/app/views/devise/shared/_links.html.erb +22 -0
  100. data/app/views/layouts/spree/checkout.html.erb +58 -0
  101. data/app/views/layouts/spree/password.html.erb +34 -0
  102. data/app/views/layouts/spree/storefront.html.erb +38 -0
  103. data/app/views/spree/account/wished_items/create.turbo_stream.erb +8 -0
  104. data/app/views/spree/account/wished_items/destroy.turbo_stream.erb +20 -0
  105. data/app/views/spree/addresses/destroy.turbo_stream.erb +1 -0
  106. data/app/views/spree/addresses/edit.html.erb +57 -0
  107. data/app/views/spree/addresses/new.html.erb +71 -0
  108. data/app/views/spree/checkout/_address.html.erb +153 -0
  109. data/app/views/spree/checkout/_button_processing.html.erb +7 -0
  110. data/app/views/spree/checkout/_coupon_code.html.erb +55 -0
  111. data/app/views/spree/checkout/_credit_card.html.erb +12 -0
  112. data/app/views/spree/checkout/_delivery.html.erb +70 -0
  113. data/app/views/spree/checkout/_line_item.html.erb +26 -0
  114. data/app/views/spree/checkout/_line_items.html.erb +7 -0
  115. data/app/views/spree/checkout/_missing_all_line_items.html.erb +17 -0
  116. data/app/views/spree/checkout/_missing_line_items.html.erb +28 -0
  117. data/app/views/spree/checkout/_payment.html.erb +35 -0
  118. data/app/views/spree/checkout/_payment_methods.html.erb +72 -0
  119. data/app/views/spree/checkout/_payment_sources.html.erb +24 -0
  120. data/app/views/spree/checkout/_quick_checkout.html.erb +1 -0
  121. data/app/views/spree/checkout/_sidebar.html.erb +34 -0
  122. data/app/views/spree/checkout/_store_credit.html.erb +21 -0
  123. data/app/views/spree/checkout/_summary.html.erb +116 -0
  124. data/app/views/spree/checkout/_user_account.html.erb +9 -0
  125. data/app/views/spree/checkout/apply_coupon_code.turbo_stream.erb +45 -0
  126. data/app/views/spree/checkout/apply_store_credit.turbo_stream.erb +19 -0
  127. data/app/views/spree/checkout/edit.html.erb +98 -0
  128. data/app/views/spree/checkout/payment/_check.html.erb +0 -0
  129. data/app/views/spree/checkout/payment/_gateway.html.erb +74 -0
  130. data/app/views/spree/checkout/payment/_store_credit.html.erb +13 -0
  131. data/app/views/spree/checkout/remove_coupon_code.turbo_stream.erb +34 -0
  132. data/app/views/spree/checkout/remove_store_credit.turbo_stream.erb +19 -0
  133. data/app/views/spree/checkout/update.turbo_stream.erb +25 -0
  134. data/app/views/spree/home/index.html.erb +1 -0
  135. data/app/views/spree/line_items/create.turbo_stream.erb +13 -0
  136. data/app/views/spree/line_items/destroy.turbo_stream.erb +11 -0
  137. data/app/views/spree/line_items/update.turbo_stream.erb +10 -0
  138. data/app/views/spree/newsletter_subscribers/create.turbo_stream.erb +7 -0
  139. data/app/views/spree/order_status/new.html.erb +16 -0
  140. data/app/views/spree/page_sections/show.html.erb +3 -0
  141. data/app/views/spree/pages/show.html.erb +1 -0
  142. data/app/views/spree/password/show.html.erb +1 -0
  143. data/app/views/spree/posts/index.html.erb +1 -0
  144. data/app/views/spree/posts/related_products.html.erb +7 -0
  145. data/app/views/spree/posts/show.html.erb +1 -0
  146. data/app/views/spree/products/index.html.erb +1 -0
  147. data/app/views/spree/products/index.turbo_stream.erb +1 -0
  148. data/app/views/spree/products/related.html.erb +3 -0
  149. data/app/views/spree/products/show.html.erb +1 -0
  150. data/app/views/spree/search/show.html.erb +6 -0
  151. data/app/views/spree/search/show.turbo_stream.erb +1 -0
  152. data/app/views/spree/search/suggestions.turbo_stream.erb +8 -0
  153. data/app/views/spree/seo/robots.text.erb +31 -0
  154. data/app/views/spree/seo/sitemap.xml.erb +25 -0
  155. data/app/views/spree/shared/_fonts.html.erb +14 -0
  156. data/app/views/spree/shared/_head.html.erb +36 -0
  157. data/app/views/spree/shared/_load_more_products.turbo_stream.erb +7 -0
  158. data/app/views/spree/shared/_product_listing_page.html.erb +11 -0
  159. data/app/views/spree/shared/_products.html.erb +1 -0
  160. data/app/views/spree/taxonomies/show.html.erb +1 -0
  161. data/app/views/spree/taxons/show.html.erb +1 -0
  162. data/app/views/spree/taxons/show.turbo_stream.erb +1 -0
  163. data/app/views/spree/waitlists/create.turbo_stream.erb +9 -0
  164. data/app/views/themes/default/kaminari/storefront/_first_page.html.erb +8 -0
  165. data/app/views/themes/default/kaminari/storefront/_gap.html.erb +8 -0
  166. data/app/views/themes/default/kaminari/storefront/_last_page.html.erb +8 -0
  167. data/app/views/themes/default/kaminari/storefront/_next_page.html.erb +13 -0
  168. data/app/views/themes/default/kaminari/storefront/_page.html.erb +10 -0
  169. data/app/views/themes/default/kaminari/storefront/_paginator.html.erb +27 -0
  170. data/app/views/themes/default/kaminari/storefront/_prev_page.html.erb +13 -0
  171. data/app/views/themes/default/spree/account/_account_nav.html.erb +46 -0
  172. data/app/views/themes/default/spree/account/_order.html.erb +39 -0
  173. data/app/views/themes/default/spree/account/_orders.html.erb +16 -0
  174. data/app/views/themes/default/spree/account/addresses/_address.html.erb +42 -0
  175. data/app/views/themes/default/spree/account/addresses/index.html.erb +28 -0
  176. data/app/views/themes/default/spree/account/newsletter/_newsletter_settings.html.erb +13 -0
  177. data/app/views/themes/default/spree/account/newsletter/edit.html.erb +16 -0
  178. data/app/views/themes/default/spree/account/newsletter/update.html.erb +1 -0
  179. data/app/views/themes/default/spree/account/orders/index.html.erb +24 -0
  180. data/app/views/themes/default/spree/account/orders/show.html.erb +22 -0
  181. data/app/views/themes/default/spree/account/profile/edit.html.erb +36 -0
  182. data/app/views/themes/default/spree/account/store_credits/_store_credit_event.html.erb +29 -0
  183. data/app/views/themes/default/spree/account/store_credits/index.html.erb +31 -0
  184. data/app/views/themes/default/spree/checkout/_footer.html.erb +10 -0
  185. data/app/views/themes/default/spree/checkout/complete.html.erb +84 -0
  186. data/app/views/themes/default/spree/contacts/new.html.erb +23 -0
  187. data/app/views/themes/default/spree/orders/_cart.html.erb +14 -0
  188. data/app/views/themes/default/spree/orders/_empty.html.erb +11 -0
  189. data/app/views/themes/default/spree/orders/_line_item.html.erb +47 -0
  190. data/app/views/themes/default/spree/orders/_line_item_quantity.html.erb +11 -0
  191. data/app/views/themes/default/spree/orders/_summary.html.erb +41 -0
  192. data/app/views/themes/default/spree/orders/edit.html.erb +18 -0
  193. data/app/views/themes/default/spree/orders/show.html.erb +6 -0
  194. data/app/views/themes/default/spree/page_sections/_announcement_bar.html.erb +10 -0
  195. data/app/views/themes/default/spree/page_sections/_custom_code.html.erb +5 -0
  196. data/app/views/themes/default/spree/page_sections/_featured_product.html.erb +136 -0
  197. data/app/views/themes/default/spree/page_sections/_featured_taxon.html.erb +116 -0
  198. data/app/views/themes/default/spree/page_sections/_featured_taxons.html.erb +71 -0
  199. data/app/views/themes/default/spree/page_sections/_footer.html.erb +62 -0
  200. data/app/views/themes/default/spree/page_sections/_header.html.erb +166 -0
  201. data/app/views/themes/default/spree/page_sections/_image_banner.html.erb +57 -0
  202. data/app/views/themes/default/spree/page_sections/_image_with_text.html.erb +66 -0
  203. data/app/views/themes/default/spree/page_sections/_main_password_footer.html.erb +64 -0
  204. data/app/views/themes/default/spree/page_sections/_main_password_header.html.erb +54 -0
  205. data/app/views/themes/default/spree/page_sections/_newsletter.html.erb +47 -0
  206. data/app/views/themes/default/spree/page_sections/_page_title.html.erb +7 -0
  207. data/app/views/themes/default/spree/page_sections/_post_details.html.erb +19 -0
  208. data/app/views/themes/default/spree/page_sections/_post_grid.html.erb +11 -0
  209. data/app/views/themes/default/spree/page_sections/_product_details.html.erb +102 -0
  210. data/app/views/themes/default/spree/page_sections/_product_grid.html.erb +52 -0
  211. data/app/views/themes/default/spree/page_sections/_related_products.html.erb +15 -0
  212. data/app/views/themes/default/spree/page_sections/_rich_text.html.erb +18 -0
  213. data/app/views/themes/default/spree/page_sections/_taxon_banner.html.erb +37 -0
  214. data/app/views/themes/default/spree/page_sections/_taxon_grid.html.erb +103 -0
  215. data/app/views/themes/default/spree/page_sections/_video.html.erb +27 -0
  216. data/app/views/themes/default/spree/page_sections/nav/_desktop.html.erb +49 -0
  217. data/app/views/themes/default/spree/page_sections/nav/_mobile.html.erb +136 -0
  218. data/app/views/themes/default/spree/policies/show.html.erb +11 -0
  219. data/app/views/themes/default/spree/posts/_json_ld.html.erb +20 -0
  220. data/app/views/themes/default/spree/posts/_pagination.html.erb +1 -0
  221. data/app/views/themes/default/spree/posts/_post.html.erb +13 -0
  222. data/app/views/themes/default/spree/products/_add_to_cart_button.html.erb +58 -0
  223. data/app/views/themes/default/spree/products/_add_to_waitlist.html.erb +36 -0
  224. data/app/views/themes/default/spree/products/_add_to_wishlist.html.erb +33 -0
  225. data/app/views/themes/default/spree/products/_breadcrumbs.html.erb +23 -0
  226. data/app/views/themes/default/spree/products/_color_picker.html.erb +19 -0
  227. data/app/views/themes/default/spree/products/_color_swatches.html.erb +61 -0
  228. data/app/views/themes/default/spree/products/_details.html.erb +55 -0
  229. data/app/views/themes/default/spree/products/_featured_image.html.erb +37 -0
  230. data/app/views/themes/default/spree/products/_filters.html.erb +45 -0
  231. data/app/views/themes/default/spree/products/_json_ld.html.erb +38 -0
  232. data/app/views/themes/default/spree/products/_json_ld_list.html.erb +9 -0
  233. data/app/views/themes/default/spree/products/_json_ld_variant.html.erb +10 -0
  234. data/app/views/themes/default/spree/products/_label.html.erb +26 -0
  235. data/app/views/themes/default/spree/products/_media_gallery.html.erb +94 -0
  236. data/app/views/themes/default/spree/products/_price.html.erb +59 -0
  237. data/app/views/themes/default/spree/products/_product.html.erb +62 -0
  238. data/app/views/themes/default/spree/products/_quantity_selector.html.erb +32 -0
  239. data/app/views/themes/default/spree/products/_returns_policy_modal.html.erb +22 -0
  240. data/app/views/themes/default/spree/products/_show_more_button.html.erb +8 -0
  241. data/app/views/themes/default/spree/products/_sort.html.erb +45 -0
  242. data/app/views/themes/default/spree/products/_swiper.html.erb +85 -0
  243. data/app/views/themes/default/spree/products/_tags.html.erb +0 -0
  244. data/app/views/themes/default/spree/products/_variant_options.html.erb +71 -0
  245. data/app/views/themes/default/spree/products/_variant_picker.html.erb +50 -0
  246. data/app/views/themes/default/spree/products/filters/_availability.html.erb +32 -0
  247. data/app/views/themes/default/spree/products/filters/_colors.html.erb +23 -0
  248. data/app/views/themes/default/spree/products/filters/_generic.html.erb +75 -0
  249. data/app/views/themes/default/spree/products/filters/_price.html.erb +35 -0
  250. data/app/views/themes/default/spree/products/filters/_taxons.erb +78 -0
  251. data/app/views/themes/default/spree/search/_suggestions.html.erb +92 -0
  252. data/app/views/themes/default/spree/settings/show.html.erb +32 -0
  253. data/app/views/themes/default/spree/shared/_account_pane.html.erb +28 -0
  254. data/app/views/themes/default/spree/shared/_address.html.erb +35 -0
  255. data/app/views/themes/default/spree/shared/_cart_icon.html.erb +13 -0
  256. data/app/views/themes/default/spree/shared/_cart_pane.html.erb +38 -0
  257. data/app/views/themes/default/spree/shared/_css_variables.html.erb +54 -0
  258. data/app/views/themes/default/spree/shared/_custom_head.html.erb +0 -0
  259. data/app/views/themes/default/spree/shared/_error_messages.html.erb +9 -0
  260. data/app/views/themes/default/spree/shared/_error_messages_without_base_attribute.html.erb +15 -0
  261. data/app/views/themes/default/spree/shared/_flash.html.erb +16 -0
  262. data/app/views/themes/default/spree/shared/_flashes.html.erb +10 -0
  263. data/app/views/themes/default/spree/shared/_json_ld.html.erb +32 -0
  264. data/app/views/themes/default/spree/shared/_line_item_options.html.erb +18 -0
  265. data/app/views/themes/default/spree/shared/_logo.html.erb +42 -0
  266. data/app/views/themes/default/spree/shared/_meta_tags.html.erb +45 -0
  267. data/app/views/themes/default/spree/shared/_order_details.html.erb +106 -0
  268. data/app/views/themes/default/spree/shared/_order_line_item.html.erb +65 -0
  269. data/app/views/themes/default/spree/shared/_order_shipment.html.erb +71 -0
  270. data/app/views/themes/default/spree/shared/_search.html.erb +32 -0
  271. data/app/views/themes/default/spree/shared/_title.html.erb +3 -0
  272. data/app/views/themes/default/spree/shared/_wishlist_icon.html.erb +13 -0
  273. data/app/views/themes/default/spree/shared/icons/_account.html.erb +17 -0
  274. data/app/views/themes/default/spree/shared/icons/_arrow-left.html.erb +8 -0
  275. data/app/views/themes/default/spree/shared/icons/_arrow-right.html.erb +3 -0
  276. data/app/views/themes/default/spree/shared/icons/_bell.html.erb +9 -0
  277. data/app/views/themes/default/spree/shared/icons/_cart.html.erb +10 -0
  278. data/app/views/themes/default/spree/shared/icons/_cart_48.html.erb +6 -0
  279. data/app/views/themes/default/spree/shared/icons/_check.html.erb +4 -0
  280. data/app/views/themes/default/spree/shared/icons/_chevron.html.erb +15 -0
  281. data/app/views/themes/default/spree/shared/icons/_chevron_down.html.erb +5 -0
  282. data/app/views/themes/default/spree/shared/icons/_chevron_right.html.erb +15 -0
  283. data/app/views/themes/default/spree/shared/icons/_chevron_up.html.erb +3 -0
  284. data/app/views/themes/default/spree/shared/icons/_close.html.erb +9 -0
  285. data/app/views/themes/default/spree/shared/icons/_cross.html.erb +16 -0
  286. data/app/views/themes/default/spree/shared/icons/_delete.html.erb +3 -0
  287. data/app/views/themes/default/spree/shared/icons/_delivery.html.erb +5 -0
  288. data/app/views/themes/default/spree/shared/icons/_disabled.html.erb +13 -0
  289. data/app/views/themes/default/spree/shared/icons/_edit.html.erb +3 -0
  290. data/app/views/themes/default/spree/shared/icons/_facebook.html.erb +16 -0
  291. data/app/views/themes/default/spree/shared/icons/_filter.html.erb +8 -0
  292. data/app/views/themes/default/spree/shared/icons/_heart.html.erb +12 -0
  293. data/app/views/themes/default/spree/shared/icons/_info.html.erb +7 -0
  294. data/app/views/themes/default/spree/shared/icons/_instagram.html.erb +18 -0
  295. data/app/views/themes/default/spree/shared/icons/_lock.html.erb +13 -0
  296. data/app/views/themes/default/spree/shared/icons/_menu.html.erb +10 -0
  297. data/app/views/themes/default/spree/shared/icons/_minus.html.erb +5 -0
  298. data/app/views/themes/default/spree/shared/icons/_pinch.html.erb +6 -0
  299. data/app/views/themes/default/spree/shared/icons/_pinterest.html.erb +8 -0
  300. data/app/views/themes/default/spree/shared/icons/_plus.html.erb +17 -0
  301. data/app/views/themes/default/spree/shared/icons/_return.html.erb +11 -0
  302. data/app/views/themes/default/spree/shared/icons/_search.html.erb +17 -0
  303. data/app/views/themes/default/spree/shared/icons/_spinner.html.erb +1 -0
  304. data/app/views/themes/default/spree/shared/icons/_spotify.html.erb +8 -0
  305. data/app/views/themes/default/spree/shared/icons/_tiktok.html.erb +9 -0
  306. data/app/views/themes/default/spree/shared/icons/_twitter.html.erb +16 -0
  307. data/app/views/themes/default/spree/shared/icons/_youtube.html.erb +9 -0
  308. data/app/views/themes/default/spree/shared/icons/_zoom.html.erb +10 -0
  309. data/app/views/themes/default/spree/wishlists/_no_wished_items.html.erb +10 -0
  310. data/app/views/themes/default/spree/wishlists/_wished_item.html.erb +38 -0
  311. data/app/views/themes/default/spree/wishlists/show.html.erb +17 -0
  312. data/config/i18n-tasks.yml +176 -0
  313. data/config/importmap.rb +22 -0
  314. data/config/initializers/assets.rb +1 -0
  315. data/config/initializers/heroicon.rb +10 -0
  316. data/config/locales/en.yml +76 -0
  317. data/config/routes.rb +88 -0
  318. data/lib/generators/spree/storefront/install/install_generator.rb +45 -0
  319. data/lib/generators/spree/storefront/install/templates/application.tailwind.css +1760 -0
  320. data/lib/generators/spree/storefront/install/templates/dev +16 -0
  321. data/lib/generators/spree/storefront/install/templates/tailwind.config.js +128 -0
  322. data/lib/generators/spree/storefront/theme/templates/model.rb.tt +12 -0
  323. data/lib/generators/spree/storefront/theme/theme_generator.rb +41 -0
  324. data/lib/spree/storefront/configuration.rb +11 -0
  325. data/lib/spree/storefront/engine.rb +51 -0
  326. data/lib/spree/storefront/testing_support/capybara_utils.rb +13 -0
  327. data/lib/spree/storefront.rb +16 -0
  328. data/lib/spree_storefront.rb +1 -0
  329. data/vendor/colornames.json +1 -0
  330. data/vendor/javascript/@kanety--stimulus-accordion.js +4 -0
  331. data/vendor/javascript/@stimulus-components--carousel.js +4 -0
  332. data/vendor/javascript/card-validator.js +4 -0
  333. data/vendor/javascript/credit-card-type.js +4 -0
  334. data/vendor/javascript/headroom.js.js +19 -0
  335. data/vendor/javascript/nouislider.js +4 -0
  336. data/vendor/javascript/photoswipe--dist--photoswipe-lightbox.esm.js.js +667 -0
  337. data/vendor/javascript/photoswipe.js +1675 -0
  338. data/vendor/javascript/stimulus-read-more.js +4 -0
  339. data/vendor/javascript/stimulus-scroll-to.js +4 -0
  340. data/vendor/javascript/swiper--bundle.js +4 -0
  341. metadata +567 -0
@@ -0,0 +1,104 @@
1
+ # overwrote this controller to drop empty and show actions
2
+ # show action has it's own controller order_status
3
+ # empty is not needed anymore
4
+ module Spree
5
+ class OrdersController < StoreController
6
+ include Spree::Core::ControllerHelpers::Order
7
+ include CartMethods
8
+
9
+ helper 'spree/products'
10
+
11
+ before_action :assign_order_with_lock, only: :update
12
+
13
+ # GET /orders/:id
14
+ def show
15
+ @order = complete_order_finder.new(number: params[:id], token: params[:token], store: current_store).execute.first
16
+
17
+ raise ActiveRecord::RecordNotFound if @order.blank? || !authorize_access
18
+
19
+ @shipments = @order.shipments.includes(:stock_location, :address, selected_shipping_rate: :shipping_method, inventory_units: :line_item)
20
+ end
21
+
22
+ # PUT /cart
23
+ def update
24
+ @variant = current_store.variants.find(params[:variant_id]) if params[:variant_id]
25
+ @result = cart_update_service.call(order: @order, params: order_params)
26
+
27
+ if @result.success?
28
+ if params.key?(:checkout)
29
+ @order.next if @order.cart?
30
+ redirect_to spree.checkout_state_path(@order.token, @order.checkout_steps.first)
31
+ else
32
+ redirect_to spree.cart_path
33
+ end
34
+ else
35
+ render :edit, status: :unprocessable_entity
36
+ end
37
+ end
38
+
39
+ # GET /cart
40
+ def edit
41
+ flash.keep if request.format.turbo_stream?
42
+ @order = current_order || find_order_by_cookie
43
+ associate_user
44
+
45
+ remove_out_of_stock_items
46
+ load_line_items
47
+ end
48
+
49
+ private
50
+
51
+ def authorize_access
52
+ return true if @order.user_id.nil?
53
+
54
+ @order.user == try_spree_current_user
55
+ end
56
+
57
+ def find_order_by_cookie
58
+ if order_token.present?
59
+ current_store.orders.incomplete.not_canceled.
60
+ includes(line_items: [variant: [:images, :product, { option_values: :option_type }]]).
61
+ find_by(token: order_token)
62
+ else
63
+ current_store.orders.incomplete.new
64
+ end
65
+ end
66
+
67
+ def accurate_title
68
+ if action_name == 'edit' || action_name == 'update'
69
+ Spree.t(:shopping_cart)
70
+ else
71
+ Spree.t(:order_number, number: @order&.number)
72
+ end
73
+ end
74
+
75
+ def order_params
76
+ if params[:order]
77
+ params[:order].permit(*permitted_order_attributes)
78
+ else
79
+ {}
80
+ end
81
+ end
82
+
83
+ def cart_remove_out_of_stock_items_service
84
+ Spree::Dependencies.cart_remove_out_of_stock_items_service.constantize
85
+ end
86
+
87
+ def cart_update_service
88
+ Spree::Dependencies.cart_update_service.constantize
89
+ end
90
+
91
+ def complete_order_finder
92
+ Spree::Dependencies.completed_order_finder.constantize
93
+ end
94
+
95
+ def remove_out_of_stock_items
96
+ return unless @order&.persisted?
97
+
98
+ ActiveRecord::Base.connected_to(role: :writing) do
99
+ @order, messages = cart_remove_out_of_stock_items_service.call(order: @order).value
100
+ flash[:error] = messages.to_sentence if messages.any?
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class PageSectionsController < StoreController
3
+ helper_method :section_variables
4
+
5
+ def show
6
+ @section = Spree::PageSection.with_deleted.find(params[:id])
7
+ end
8
+
9
+ def section_variables
10
+ @section_variables ||= begin
11
+ variables = {}
12
+
13
+ variables
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ class PagesController < StoreController
3
+ def show
4
+ @current_page = @page = current_store.pages.custom.friendly.find(params[:id])
5
+ end
6
+
7
+ private
8
+
9
+ def title
10
+ @title ||= @page.meta_title.presence || @page.name
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ class PasswordController < StoreController
3
+ layout 'spree/password'
4
+
5
+ skip_before_action :redirect_to_password
6
+
7
+ def show
8
+ @current_page = current_theme.pages.find_by(type: 'Spree::Pages::Password')
9
+ end
10
+
11
+ def check
12
+ if params[:password] == current_store.storefront_password
13
+ session[:password_valid] = true
14
+ redirect_to root_path
15
+ else
16
+ flash[:error] = 'Incorrect password. Please try again.'
17
+ redirect_to password_path
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class PoliciesController < StoreController
3
+ def show
4
+ if params[:id].in?(supported_policies)
5
+ @policy = current_store.send("customer_#{params[:id]}")
6
+ else
7
+ raise ActiveRecord::RecordNotFound
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def supported_policies
14
+ %w[privacy_policy terms_of_service returns_policy shipping_policy]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,76 @@
1
+ module Spree
2
+ class PostsController < Spree::StoreController
3
+ before_action :load_category, if: -> { params[:category_id].present? }, only: :index
4
+ before_action :load_tag, if: -> { params[:tag].present? }, only: :index
5
+
6
+ after_action :track_show, only: :show
7
+
8
+ def index
9
+ @current_page = current_theme.pages.find_by!(type: 'Spree::Pages::PostList')
10
+
11
+ scope = current_store.posts.published
12
+ scope = scope.tagged_with(@tag.name) if @tag.present?
13
+ scope = scope.where(post_category_id: @category.id) if @category.present?
14
+
15
+ sorted_posts = scope.order(published_at: :desc)
16
+ @posts = sorted_posts.page(params[:page]).per(20)
17
+ end
18
+
19
+ def show
20
+ if params[:preview_id].present?
21
+ preview_post = current_store.posts.friendly.find(params[:id])
22
+ raise ActiveRecord::RecordNotFound if preview_post.id.to_s != params[:preview_id]
23
+
24
+ @post ||= preview_post
25
+ else
26
+ @post = current_store.posts.friendly.published.find(params[:id])
27
+ end
28
+
29
+ @current_page = current_theme.pages.find_by!(type: 'Spree::Pages::Post')
30
+ end
31
+
32
+ def related_products
33
+ @post = Spree::Post.friendly.find(params[:id])
34
+ current_page = current_theme.pages.find_by!(type: 'Spree::Pages::Post')
35
+ @section = current_page.sections.find_by!(id: params[:section_id], type: 'Spree::PageSections::RelatedProducts')
36
+ end
37
+
38
+ private
39
+
40
+ def accurate_title
41
+ if @post
42
+ @post.meta_title.presence || @post.title
43
+ elsif @category.present? && @tag.present?
44
+ "#{@category.title} / #{@tag.name.titleize}"
45
+ elsif @category.present?
46
+ @category.title
47
+ elsif @tag.present?
48
+ Spree.t(:all_posts_with_tag, tag: @tag.name.titleize)
49
+ else
50
+ Spree.t(:all_posts)
51
+ end
52
+ end
53
+
54
+ def load_category
55
+ @category = current_store.post_categories.friendly.find(params[:category_id])
56
+ @page_description = @category.description.to_plain_text
57
+ end
58
+
59
+ def load_tag
60
+ @tag = post_tags_scope.find_by!(name: params[:tag].strip)
61
+ end
62
+
63
+ def post_tags_scope
64
+ @post_tags_scope ||= ActsAsTaggableOn::Tag.
65
+ joins(:taggings).
66
+ where('taggings.taggable_type = ?', Spree::Post.to_s).
67
+ for_context(:tags).for_tenant(current_store.id)
68
+ end
69
+
70
+ def track_show
71
+ return if turbo_frame_request? || turbo_stream_request?
72
+
73
+ track_event('post_viewed', { post_id: @post.id })
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,99 @@
1
+ module Spree
2
+ class ProductsController < Spree::StoreController
3
+ helper 'spree/products'
4
+
5
+ after_action :track_show, only: :show
6
+ after_action :track_index, only: :index
7
+
8
+ def index
9
+ @current_page = current_theme.pages.find_by(type: 'Spree::Pages::ShopAll')
10
+ end
11
+
12
+ def show
13
+ load_product
14
+ redirect_if_legacy_path
15
+
16
+ @current_page = current_theme.pages.product_details.first
17
+ end
18
+
19
+ def related
20
+ @current_page = current_theme.pages.product_details.first
21
+ section_scope = @current_page.sections.related_products
22
+ @section = section_scope.find_by(id: params[:section_id]) || section_scope.first
23
+ load_product
24
+ # An interesting thing is that since we're querying the translations table (in the multi_search),
25
+ # when using not default locale, our related products are different for different locales.
26
+ @products = current_store.products.active(current_currency).where.not(id: @product.id).
27
+ multi_search(@product.name).includes(storefront_products_includes).
28
+ limit(@section.preferred_max_products_to_show)
29
+ end
30
+
31
+ private
32
+
33
+ def accurate_title
34
+ load_product if action_name == 'show' # we need this for ahoy analytics
35
+
36
+ if @product
37
+ @product.meta_title.blank? ? @product.name : @product.meta_title
38
+ else
39
+ params[:q].present? ? Spree.t(:search_results_for, query: params[:q]) : Spree.t(:shop_all)
40
+ end
41
+ end
42
+
43
+ def load_product
44
+ if params[:preview_id].present?
45
+ possible_product = find_with_fallback_default_locale { current_store.products.friendly.find(params[:id]) }
46
+
47
+ raise ActiveRecord::RecordNotFound if possible_product.id.to_s != params[:preview_id].to_s
48
+
49
+ @product ||= possible_product
50
+ else
51
+ @product ||= find_with_fallback_default_locale { current_store.products.for_user(try_spree_current_user).friendly.find(params[:id]) }
52
+ end
53
+
54
+ options_hash = if params[:options].present?
55
+ params[:options].split(',').to_h do |option|
56
+ key, *value = option.split(':')
57
+ [key, value.join(':')]
58
+ end
59
+ else
60
+ {}
61
+ end
62
+
63
+ variant_finder = Spree::Storefront::VariantFinder.new(
64
+ product: @product,
65
+ variant_id: params[:variant_id],
66
+ current_currency: current_currency,
67
+ options_hash: options_hash
68
+ )
69
+
70
+ @selected_variant, @variant_from_options =
71
+ Rails.cache.fetch([@product.cache_key_with_version, 'variant-finder', current_currency, params[:variant_id], options_hash].compact) do
72
+ variant_finder.find
73
+ end
74
+ end
75
+
76
+ def redirect_if_legacy_path
77
+ # If an old id or a numeric id was used to find the record,
78
+ # we should do a 301 redirect that uses the current friendly id.
79
+ if params[:id] != @product.friendly_id
80
+ params[:id] = @product.friendly_id
81
+ params.permit!
82
+ redirect_to url_for(params), status: :moved_permanently
83
+ end
84
+ end
85
+
86
+ def track_show
87
+ return if turbo_frame_request? || turbo_stream_request?
88
+ return if params[:options].present? # we don't want to track product views for variants
89
+
90
+ track_event('product_viewed', { product: @product })
91
+ end
92
+
93
+ def track_index
94
+ return if turbo_frame_request? || turbo_stream_request?
95
+
96
+ track_event('product_list_viewed', { taxon: @taxon })
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ class SearchController < StoreController
3
+ after_action :track, only: :show
4
+
5
+ helper_method :query
6
+
7
+ def show
8
+ @current_page = current_theme.pages.find_by(type: 'Spree::Pages::SearchResults')
9
+ end
10
+
11
+ def suggestions
12
+ @products = []
13
+ @taxons = []
14
+
15
+ if query.present? && query.length >= Spree::Storefront::Config.search_min_query_length
16
+ products_scope = current_store.products.active(current_currency).multi_search(query)
17
+ @products = products_scope.includes(storefront_products_includes)
18
+ @taxons = current_store.taxons.search_by_name(query)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def query
25
+ @query ||= params[:q].presence&.strip_html_tags&.strip
26
+ end
27
+
28
+ def track
29
+ return if turbo_frame_request? || turbo_stream_request?
30
+ return if query.blank?
31
+
32
+ track_event('product_searched', { query: query })
33
+ end
34
+
35
+ def default_products_sort
36
+ 'manual'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ class SeoController < StoreController
3
+ include BaseHelper
4
+ include StorefrontHelper
5
+
6
+ def robots
7
+ render view: 'seo/robots', layout: false, content_type: 'text/plain', locals: { store: current_store }
8
+ end
9
+
10
+ def sitemap
11
+ unless current_store.prefers_index_in_search_engines?
12
+ head :not_found
13
+ return
14
+ end
15
+
16
+ respond_to do |format|
17
+ format.xml
18
+ format.gzip do
19
+ gz_xml = ActiveSupport::Gzip.compress(render_to_string(template: 'spree/seo/sitemap', formats: [:xml]))
20
+ send_data(gz_xml, filename: 'sitemap.xml.gz', type: 'application/x-gzip', disposition: 'inline')
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ module Spree
2
+ class SettingsController < Spree::StoreController
3
+ def show; end
4
+
5
+ def update
6
+ new_locale = (params[:switch_to_locale] || params[:locale]).to_s
7
+ new_currency = params[:switch_to_currency]&.upcase
8
+
9
+ if new_currency.present? && supported_currency?(new_currency)
10
+ current_order&.update(currency: new_currency)
11
+ session[:currency] = new_currency
12
+ end
13
+
14
+ if new_locale.present? && supported_locale?(new_locale)
15
+ if try_spree_current_user && try_spree_current_user.selected_locale != new_locale
16
+ try_spree_current_user.update!(selected_locale: new_locale)
17
+ end
18
+
19
+ locale_for_slug = new_locale
20
+ new_locale = nil if new_locale.to_s == current_store.default_locale.to_s
21
+
22
+ if request.referer.present?
23
+ uri = URI(request.referer)
24
+
25
+ previous_params = begin
26
+ Spree::Core::Engine.routes.recognize_path(uri.path)
27
+ rescue ActionController::RoutingError
28
+ Rails.application.routes.recognize_path(uri.path)
29
+ end
30
+
31
+ redirect_to spree.root_path(locale: new_locale) && return if previous_params.blank?
32
+
33
+ new_params = previous_params.clone.merge(locale: new_locale)
34
+
35
+ # We only care if the previous url was for a specific record, because we need to find it with the slug/permalink from the new locale
36
+ new_params[:id] = find_slug_in_current_locale(previous_params, locale_for_slug)
37
+
38
+ redirect_to new_params
39
+ else
40
+ redirect_to spree.root_path(locale: new_locale)
41
+ end
42
+ else
43
+ redirect_to spree.root_path
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def find_slug_in_current_locale(params, new_locale)
50
+ if params[:id].present?
51
+ case params[:controller]
52
+ when 'spree/products'
53
+ old_product = find_with_fallback(params[:locale]) { current_store.products.friendly.find(params[:id]) }
54
+ old_product.slug(locale: new_locale) || old_product.slug(locale: current_store.default_locale)
55
+ when 'spree/taxons'
56
+ old_taxon = find_with_fallback(params[:locale]) { current_store.taxons.friendly.find(params[:id]) }
57
+ old_taxon.permalink(locale: new_locale) || old_taxon.permalink(locale: current_store.default_locale)
58
+ else
59
+ params[:id]
60
+ end
61
+ end
62
+ end
63
+
64
+ def find_with_fallback(locale, &block)
65
+ Mobility.with_locale(locale) { find_with_fallback_default_locale(&block) }
66
+ end
67
+ end
68
+ end