@pradip1995/create-storefront 1.0.1

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 (338) hide show
  1. package/bin/create-storefront.js +239 -0
  2. package/lib/kit-next-config.js +84 -0
  3. package/package.json +32 -0
  4. package/templates/storefront/.eslintrc.json +3 -0
  5. package/templates/storefront/README.md +35 -0
  6. package/templates/storefront/check-env-variables.js +51 -0
  7. package/templates/storefront/kit-next-config.js +71 -0
  8. package/templates/storefront/next-env.d.ts +5 -0
  9. package/templates/storefront/next.config.js +25 -0
  10. package/templates/storefront/package.json +56 -0
  11. package/templates/storefront/postcss.config.js +6 -0
  12. package/templates/storefront/public/favicon.png +0 -0
  13. package/templates/storefront/src/app/[countryCode]/(checkout)/checkout/page.tsx +23 -0
  14. package/templates/storefront/src/app/[countryCode]/(checkout)/checkout/payment/page.tsx +47 -0
  15. package/templates/storefront/src/app/[countryCode]/(checkout)/layout.tsx +31 -0
  16. package/templates/storefront/src/app/[countryCode]/(checkout)/not-found.tsx +19 -0
  17. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/addresses/page.tsx +31 -0
  18. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/loading.tsx +9 -0
  19. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/orders/details/[id]/page.tsx +35 -0
  20. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/orders/exchange/[id]/page.tsx +47 -0
  21. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/orders/page.tsx +28 -0
  22. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/orders/return/[id]/page.tsx +66 -0
  23. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/page.tsx +22 -0
  24. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/payment-methods/page.tsx +23 -0
  25. package/templates/storefront/src/app/[countryCode]/(main)/account/@dashboard/profile/page.tsx +43 -0
  26. package/templates/storefront/src/app/[countryCode]/(main)/account/@login/default.tsx +11 -0
  27. package/templates/storefront/src/app/[countryCode]/(main)/account/@login/page.tsx +18 -0
  28. package/templates/storefront/src/app/[countryCode]/(main)/account/guest-orders/page.tsx +13 -0
  29. package/templates/storefront/src/app/[countryCode]/(main)/account/layout.tsx +22 -0
  30. package/templates/storefront/src/app/[countryCode]/(main)/account/loading.tsx +9 -0
  31. package/templates/storefront/src/app/[countryCode]/(main)/cart/loading.tsx +5 -0
  32. package/templates/storefront/src/app/[countryCode]/(main)/cart/not-found.tsx +21 -0
  33. package/templates/storefront/src/app/[countryCode]/(main)/cart/page.tsx +23 -0
  34. package/templates/storefront/src/app/[countryCode]/(main)/categories/[...category]/page.tsx +11 -0
  35. package/templates/storefront/src/app/[countryCode]/(main)/collections/[handle]/page.tsx +11 -0
  36. package/templates/storefront/src/app/[countryCode]/(main)/contact/page.tsx +21 -0
  37. package/templates/storefront/src/app/[countryCode]/(main)/guest-orders/page.tsx +12 -0
  38. package/templates/storefront/src/app/[countryCode]/(main)/help/page.tsx +28 -0
  39. package/templates/storefront/src/app/[countryCode]/(main)/layout.tsx +21 -0
  40. package/templates/storefront/src/app/[countryCode]/(main)/not-found.tsx +20 -0
  41. package/templates/storefront/src/app/[countryCode]/(main)/order/[id]/confirmed/loading.tsx +5 -0
  42. package/templates/storefront/src/app/[countryCode]/(main)/order/[id]/confirmed/page.tsx +23 -0
  43. package/templates/storefront/src/app/[countryCode]/(main)/order/[id]/transfer/[token]/accept/page.tsx +41 -0
  44. package/templates/storefront/src/app/[countryCode]/(main)/order/[id]/transfer/[token]/decline/page.tsx +41 -0
  45. package/templates/storefront/src/app/[countryCode]/(main)/order/[id]/transfer/[token]/page.tsx +38 -0
  46. package/templates/storefront/src/app/[countryCode]/(main)/order/exchange/[id]/page.tsx +47 -0
  47. package/templates/storefront/src/app/[countryCode]/(main)/order/return/[id]/page.tsx +61 -0
  48. package/templates/storefront/src/app/[countryCode]/(main)/orders/[id]/page.tsx +33 -0
  49. package/templates/storefront/src/app/[countryCode]/(main)/page.tsx +24 -0
  50. package/templates/storefront/src/app/[countryCode]/(main)/privacy-policy/page.tsx +173 -0
  51. package/templates/storefront/src/app/[countryCode]/(main)/products/[handle]/page.tsx +193 -0
  52. package/templates/storefront/src/app/[countryCode]/(main)/reset-password/page.tsx +192 -0
  53. package/templates/storefront/src/app/[countryCode]/(main)/store/page.tsx +72 -0
  54. package/templates/storefront/src/app/[countryCode]/(main)/terms-of-use/page.tsx +179 -0
  55. package/templates/storefront/src/app/[countryCode]/(main)/wishlist/page.tsx +19 -0
  56. package/templates/storefront/src/app/api/meta/event/route.ts +63 -0
  57. package/templates/storefront/src/app/auth/customer/google/callback/page.tsx +126 -0
  58. package/templates/storefront/src/app/layout.tsx +104 -0
  59. package/templates/storefront/src/app/not-found.tsx +30 -0
  60. package/templates/storefront/src/app/opengraph-image.jpg +0 -0
  61. package/templates/storefront/src/app/robots.ts +15 -0
  62. package/templates/storefront/src/app/sitemap.ts +65 -0
  63. package/templates/storefront/src/app/twitter-image.jpg +0 -0
  64. package/templates/storefront/src/modules/account/components/account-deletion/index.tsx +160 -0
  65. package/templates/storefront/src/modules/account/components/account-info/index.tsx +145 -0
  66. package/templates/storefront/src/modules/account/components/account-nav/icons.tsx +43 -0
  67. package/templates/storefront/src/modules/account/components/account-nav/index.tsx +318 -0
  68. package/templates/storefront/src/modules/account/components/account-nav/logout-modal.tsx +92 -0
  69. package/templates/storefront/src/modules/account/components/account-nav/payment-methods-icon.tsx +9 -0
  70. package/templates/storefront/src/modules/account/components/address-book/index.tsx +47 -0
  71. package/templates/storefront/src/modules/account/components/address-card/add-address.tsx +377 -0
  72. package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx +468 -0
  73. package/templates/storefront/src/modules/account/components/deletion-pending-modal/index.tsx +213 -0
  74. package/templates/storefront/src/modules/account/components/forgot-password/index.tsx +1 -0
  75. package/templates/storefront/src/modules/account/components/login/index.tsx +1 -0
  76. package/templates/storefront/src/modules/account/components/order-card/index.tsx +221 -0
  77. package/templates/storefront/src/modules/account/components/order-overview/index.tsx +159 -0
  78. package/templates/storefront/src/modules/account/components/overview/index.tsx +189 -0
  79. package/templates/storefront/src/modules/account/components/profile-billing-address/index.tsx +447 -0
  80. package/templates/storefront/src/modules/account/components/profile-email/index.tsx +75 -0
  81. package/templates/storefront/src/modules/account/components/profile-form/index.tsx +416 -0
  82. package/templates/storefront/src/modules/account/components/profile-name/index.tsx +76 -0
  83. package/templates/storefront/src/modules/account/components/profile-password/index.tsx +70 -0
  84. package/templates/storefront/src/modules/account/components/profile-phone/index.tsx +185 -0
  85. package/templates/storefront/src/modules/account/components/register/index.tsx +1 -0
  86. package/templates/storefront/src/modules/account/components/return-item-selector/index.tsx +187 -0
  87. package/templates/storefront/src/modules/account/components/return-shipping-selector/index.tsx +118 -0
  88. package/templates/storefront/src/modules/account/components/transfer-request-form/index.tsx +81 -0
  89. package/templates/storefront/src/modules/account/templates/account-layout.tsx +38 -0
  90. package/templates/storefront/src/modules/account/templates/exchange-request-template.tsx +389 -0
  91. package/templates/storefront/src/modules/account/templates/guest-orders-template.tsx +123 -0
  92. package/templates/storefront/src/modules/account/templates/login-template.tsx +44 -0
  93. package/templates/storefront/src/modules/account/templates/payment-methods-template.tsx +478 -0
  94. package/templates/storefront/src/modules/account/templates/return-request-template.tsx +300 -0
  95. package/templates/storefront/src/modules/cart/components/abandoned-carts/ScrollToPendingOrdersButton.tsx +21 -0
  96. package/templates/storefront/src/modules/cart/components/abandoned-carts/index.tsx +335 -0
  97. package/templates/storefront/src/modules/cart/components/applied-promotions/index.tsx +121 -0
  98. package/templates/storefront/src/modules/cart/components/cart-delivery-selection/index.tsx +203 -0
  99. package/templates/storefront/src/modules/cart/components/cart-item-card/index.tsx +476 -0
  100. package/templates/storefront/src/modules/cart/components/cart-item-select/index.tsx +73 -0
  101. package/templates/storefront/src/modules/cart/components/cart-view-tracker/index.tsx +44 -0
  102. package/templates/storefront/src/modules/cart/components/delivery-information/index.tsx +89 -0
  103. package/templates/storefront/src/modules/cart/components/empty-cart-message/index.tsx +38 -0
  104. package/templates/storefront/src/modules/cart/components/item/index.tsx +150 -0
  105. package/templates/storefront/src/modules/cart/components/pincode-checker/index.tsx +174 -0
  106. package/templates/storefront/src/modules/cart/components/sign-in-prompt/index.tsx +26 -0
  107. package/templates/storefront/src/modules/cart/components/you-may-also-like/index.tsx +137 -0
  108. package/templates/storefront/src/modules/cart/templates/index.tsx +88 -0
  109. package/templates/storefront/src/modules/cart/templates/items.tsx +49 -0
  110. package/templates/storefront/src/modules/cart/templates/preview.tsx +51 -0
  111. package/templates/storefront/src/modules/cart/templates/summary.tsx +29 -0
  112. package/templates/storefront/src/modules/checkout/components/add-address-modal/index.tsx +390 -0
  113. package/templates/storefront/src/modules/checkout/components/address-card/index.tsx +135 -0
  114. package/templates/storefront/src/modules/checkout/components/address-select/index.tsx +116 -0
  115. package/templates/storefront/src/modules/checkout/components/addresses/index.tsx +605 -0
  116. package/templates/storefront/src/modules/checkout/components/back-link/index.tsx +32 -0
  117. package/templates/storefront/src/modules/checkout/components/billing_address/index.tsx +301 -0
  118. package/templates/storefront/src/modules/checkout/components/checkout-begin-tracker/index.tsx +45 -0
  119. package/templates/storefront/src/modules/checkout/components/checkout-leave-guard/index.tsx +109 -0
  120. package/templates/storefront/src/modules/checkout/components/checkout-shipping-tracker/index.tsx +45 -0
  121. package/templates/storefront/src/modules/checkout/components/country-select/index.tsx +50 -0
  122. package/templates/storefront/src/modules/checkout/components/discount-code/index.tsx +220 -0
  123. package/templates/storefront/src/modules/checkout/components/error-message/index.tsx +13 -0
  124. package/templates/storefront/src/modules/checkout/components/payment/index.tsx +572 -0
  125. package/templates/storefront/src/modules/checkout/components/payment-button/index.tsx +257 -0
  126. package/templates/storefront/src/modules/checkout/components/payment-button/razorpay-payment-button.tsx +136 -0
  127. package/templates/storefront/src/modules/checkout/components/payment-container/index.tsx +129 -0
  128. package/templates/storefront/src/modules/checkout/components/payment-test/index.tsx +12 -0
  129. package/templates/storefront/src/modules/checkout/components/payment-wrapper/index.tsx +50 -0
  130. package/templates/storefront/src/modules/checkout/components/payment-wrapper/stripe-wrapper.tsx +54 -0
  131. package/templates/storefront/src/modules/checkout/components/processing-overlay/index.tsx +83 -0
  132. package/templates/storefront/src/modules/checkout/components/review/index.tsx +60 -0
  133. package/templates/storefront/src/modules/checkout/components/select-address-modal/index.tsx +103 -0
  134. package/templates/storefront/src/modules/checkout/components/shipping/index.tsx +533 -0
  135. package/templates/storefront/src/modules/checkout/components/shipping-address/index.tsx +521 -0
  136. package/templates/storefront/src/modules/checkout/components/submit-button/index.tsx +32 -0
  137. package/templates/storefront/src/modules/checkout/templates/checkout-form/index.tsx +38 -0
  138. package/templates/storefront/src/modules/checkout/templates/checkout-summary/index.tsx +274 -0
  139. package/templates/storefront/src/modules/common/components/breadcrumb/index.tsx +43 -0
  140. package/templates/storefront/src/modules/common/components/cart-totals/index.tsx +473 -0
  141. package/templates/storefront/src/modules/common/components/checkbox/index.tsx +98 -0
  142. package/templates/storefront/src/modules/common/components/delete-button/index.tsx +156 -0
  143. package/templates/storefront/src/modules/common/components/divider/index.tsx +9 -0
  144. package/templates/storefront/src/modules/common/components/filter-checkbox-group/index.tsx +134 -0
  145. package/templates/storefront/src/modules/common/components/filter-radio-group/index.tsx +62 -0
  146. package/templates/storefront/src/modules/common/components/input/index.tsx +79 -0
  147. package/templates/storefront/src/modules/common/components/interactive-link/index.tsx +33 -0
  148. package/templates/storefront/src/modules/common/components/line-item-options/index.tsx +26 -0
  149. package/templates/storefront/src/modules/common/components/line-item-price/index.tsx +64 -0
  150. package/templates/storefront/src/modules/common/components/line-item-unit-price/index.tsx +61 -0
  151. package/templates/storefront/src/modules/common/components/localized-client-link/index.tsx +32 -0
  152. package/templates/storefront/src/modules/common/components/login-popup/index.tsx +78 -0
  153. package/templates/storefront/src/modules/common/components/modal/index.tsx +123 -0
  154. package/templates/storefront/src/modules/common/components/native-select/index.tsx +75 -0
  155. package/templates/storefront/src/modules/common/components/obfuscated-email/index.tsx +30 -0
  156. package/templates/storefront/src/modules/common/components/product/product-rating/index.tsx +172 -0
  157. package/templates/storefront/src/modules/common/components/product/review-modal/index.tsx +333 -0
  158. package/templates/storefront/src/modules/common/components/product/share-button/index.tsx +227 -0
  159. package/templates/storefront/src/modules/common/components/product/wishlist-icon/index.tsx +46 -0
  160. package/templates/storefront/src/modules/common/components/radio/index.tsx +27 -0
  161. package/templates/storefront/src/modules/common/components/select/index.tsx +164 -0
  162. package/templates/storefront/src/modules/common/components/side-panel/index.tsx +65 -0
  163. package/templates/storefront/src/modules/common/icons/arrow-left.tsx +36 -0
  164. package/templates/storefront/src/modules/common/icons/back.tsx +37 -0
  165. package/templates/storefront/src/modules/common/icons/bancontact.tsx +26 -0
  166. package/templates/storefront/src/modules/common/icons/chevron-down.tsx +30 -0
  167. package/templates/storefront/src/modules/common/icons/delivered.tsx +29 -0
  168. package/templates/storefront/src/modules/common/icons/envelope.tsx +27 -0
  169. package/templates/storefront/src/modules/common/icons/eye-off.tsx +37 -0
  170. package/templates/storefront/src/modules/common/icons/eye.tsx +37 -0
  171. package/templates/storefront/src/modules/common/icons/fast-delivery.tsx +65 -0
  172. package/templates/storefront/src/modules/common/icons/ideal.tsx +26 -0
  173. package/templates/storefront/src/modules/common/icons/lock.tsx +31 -0
  174. package/templates/storefront/src/modules/common/icons/map-pin.tsx +37 -0
  175. package/templates/storefront/src/modules/common/icons/medusa.tsx +27 -0
  176. package/templates/storefront/src/modules/common/icons/menu.tsx +45 -0
  177. package/templates/storefront/src/modules/common/icons/nextjs.tsx +27 -0
  178. package/templates/storefront/src/modules/common/icons/package.tsx +44 -0
  179. package/templates/storefront/src/modules/common/icons/paypal.tsx +30 -0
  180. package/templates/storefront/src/modules/common/icons/phone.tsx +30 -0
  181. package/templates/storefront/src/modules/common/icons/placeholder-image.tsx +44 -0
  182. package/templates/storefront/src/modules/common/icons/refresh.tsx +51 -0
  183. package/templates/storefront/src/modules/common/icons/spinner.tsx +37 -0
  184. package/templates/storefront/src/modules/common/icons/trash.tsx +51 -0
  185. package/templates/storefront/src/modules/common/icons/user.tsx +37 -0
  186. package/templates/storefront/src/modules/common/icons/x.tsx +37 -0
  187. package/templates/storefront/src/modules/contact/templates/index.tsx +272 -0
  188. package/templates/storefront/src/modules/help/templates/index.tsx +629 -0
  189. package/templates/storefront/src/modules/home/components/dynamic-banner/index.tsx +190 -0
  190. package/templates/storefront/src/modules/home/components/featured-products/index.tsx +16 -0
  191. package/templates/storefront/src/modules/home/components/featured-products/product-rail/index.tsx +51 -0
  192. package/templates/storefront/src/modules/home/components/features/index.tsx +1 -0
  193. package/templates/storefront/src/modules/home/components/hero/index.tsx +1 -0
  194. package/templates/storefront/src/modules/home/components/loved-by-moms/index.tsx +1 -0
  195. package/templates/storefront/src/modules/home/components/new-arrivals/index.tsx +1 -0
  196. package/templates/storefront/src/modules/home/components/shop-by-age/index.tsx +1 -0
  197. package/templates/storefront/src/modules/home/components/shop-by-category/index.tsx +1 -0
  198. package/templates/storefront/src/modules/home/components/testimonials/index.tsx +1 -0
  199. package/templates/storefront/src/modules/home/components/why-choose-us/dynamic-features.tsx +93 -0
  200. package/templates/storefront/src/modules/home/components/why-choose-us/index.tsx +1 -0
  201. package/templates/storefront/src/modules/layout/components/account-dropdown/index.tsx +56 -0
  202. package/templates/storefront/src/modules/layout/components/cart-button/index.tsx +8 -0
  203. package/templates/storefront/src/modules/layout/components/cart-dropdown/index.tsx +424 -0
  204. package/templates/storefront/src/modules/layout/components/cart-mismatch-banner/index.tsx +57 -0
  205. package/templates/storefront/src/modules/layout/components/cookie-consent/index.tsx +116 -0
  206. package/templates/storefront/src/modules/layout/components/country-select/index.tsx +135 -0
  207. package/templates/storefront/src/modules/layout/components/desktop-search/index.tsx +148 -0
  208. package/templates/storefront/src/modules/layout/components/dynamic-logo/index.tsx +27 -0
  209. package/templates/storefront/src/modules/layout/components/footer-categories/index.tsx +34 -0
  210. package/templates/storefront/src/modules/layout/components/footer-contact/index.tsx +87 -0
  211. package/templates/storefront/src/modules/layout/components/footer-description/index.tsx +12 -0
  212. package/templates/storefront/src/modules/layout/components/footer-logo/index.tsx +22 -0
  213. package/templates/storefront/src/modules/layout/components/footer-newsletter/index.tsx +100 -0
  214. package/templates/storefront/src/modules/layout/components/language-select/index.tsx +192 -0
  215. package/templates/storefront/src/modules/layout/components/medusa-cta/index.tsx +21 -0
  216. package/templates/storefront/src/modules/layout/components/mobile-menu/index.tsx +296 -0
  217. package/templates/storefront/src/modules/layout/components/nav-links/index.tsx +66 -0
  218. package/templates/storefront/src/modules/layout/components/nav-wrapper/index.tsx +14 -0
  219. package/templates/storefront/src/modules/layout/components/promo-bar/index.tsx +7 -0
  220. package/templates/storefront/src/modules/layout/components/promo-bar/promo-bar-content.tsx +174 -0
  221. package/templates/storefront/src/modules/layout/components/push-notification-manager/index.tsx +191 -0
  222. package/templates/storefront/src/modules/layout/components/search-panel/index.tsx +136 -0
  223. package/templates/storefront/src/modules/layout/components/side-menu/index.tsx +144 -0
  224. package/templates/storefront/src/modules/layout/components/verification-banner/index.tsx +217 -0
  225. package/templates/storefront/src/modules/layout/components/wishlist-counter/index.tsx +17 -0
  226. package/templates/storefront/src/modules/layout/templates/footer/index.tsx +7 -0
  227. package/templates/storefront/src/modules/layout/templates/nav/index.tsx +14 -0
  228. package/templates/storefront/src/modules/order/components/cancel-order-modal/index.tsx +168 -0
  229. package/templates/storefront/src/modules/order/components/help/index.tsx +25 -0
  230. package/templates/storefront/src/modules/order/components/item/index.tsx +62 -0
  231. package/templates/storefront/src/modules/order/components/items/index.tsx +44 -0
  232. package/templates/storefront/src/modules/order/components/onboarding-cta/index.tsx +28 -0
  233. package/templates/storefront/src/modules/order/components/order-confirmation-back-handler/index.tsx +28 -0
  234. package/templates/storefront/src/modules/order/components/order-details/index.tsx +63 -0
  235. package/templates/storefront/src/modules/order/components/order-purchase-tracker/index.tsx +48 -0
  236. package/templates/storefront/src/modules/order/components/order-redesign/index.tsx +887 -0
  237. package/templates/storefront/src/modules/order/components/order-summary/index.tsx +60 -0
  238. package/templates/storefront/src/modules/order/components/payment-details/index.tsx +63 -0
  239. package/templates/storefront/src/modules/order/components/shipping-details/index.tsx +73 -0
  240. package/templates/storefront/src/modules/order/components/transfer-actions/index.tsx +81 -0
  241. package/templates/storefront/src/modules/order/components/transfer-image/index.tsx +275 -0
  242. package/templates/storefront/src/modules/order/templates/order-completed-template.tsx +233 -0
  243. package/templates/storefront/src/modules/order/templates/order-details-template.tsx +128 -0
  244. package/templates/storefront/src/modules/products/components/image-gallery/index.tsx +297 -0
  245. package/templates/storefront/src/modules/products/components/product-actions/index.tsx +1400 -0
  246. package/templates/storefront/src/modules/products/components/product-actions/mobile-actions.tsx +217 -0
  247. package/templates/storefront/src/modules/products/components/product-actions/option-select.tsx +62 -0
  248. package/templates/storefront/src/modules/products/components/product-onboarding-cta/index.tsx +30 -0
  249. package/templates/storefront/src/modules/products/components/product-preview/index.tsx +5 -0
  250. package/templates/storefront/src/modules/products/components/product-preview/price.tsx +29 -0
  251. package/templates/storefront/src/modules/products/components/product-price/index.tsx +58 -0
  252. package/templates/storefront/src/modules/products/components/product-rating/index.tsx +1 -0
  253. package/templates/storefront/src/modules/products/components/product-tabs/accordion.tsx +100 -0
  254. package/templates/storefront/src/modules/products/components/product-tabs/index.tsx +127 -0
  255. package/templates/storefront/src/modules/products/components/product-tabs/ratings-tab.tsx +598 -0
  256. package/templates/storefront/src/modules/products/components/product-view-tracker/index.tsx +53 -0
  257. package/templates/storefront/src/modules/products/components/related-products/index.tsx +152 -0
  258. package/templates/storefront/src/modules/products/components/review-modal/index.tsx +1 -0
  259. package/templates/storefront/src/modules/products/components/share-button/index.tsx +1 -0
  260. package/templates/storefront/src/modules/products/components/thumbnail/index.tsx +91 -0
  261. package/templates/storefront/src/modules/products/components/wishlist-icon/index.tsx +1 -0
  262. package/templates/storefront/src/modules/products/context/product-context.tsx +52 -0
  263. package/templates/storefront/src/modules/products/templates/index.tsx +26 -0
  264. package/templates/storefront/src/modules/products/templates/product-actions-wrapper/index.tsx +1 -0
  265. package/templates/storefront/src/modules/products/templates/product-info/index.tsx +2 -0
  266. package/templates/storefront/src/modules/shipping/components/free-shipping-price-nudge/index.tsx +283 -0
  267. package/templates/storefront/src/modules/skeletons/components/skeleton-button/index.tsx +5 -0
  268. package/templates/storefront/src/modules/skeletons/components/skeleton-card-details/index.tsx +10 -0
  269. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-item/index.tsx +35 -0
  270. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-totals/index.tsx +30 -0
  271. package/templates/storefront/src/modules/skeletons/components/skeleton-code-form/index.tsx +13 -0
  272. package/templates/storefront/src/modules/skeletons/components/skeleton-line-item/index.tsx +35 -0
  273. package/templates/storefront/src/modules/skeletons/components/skeleton-order-confirmed-header/index.tsx +14 -0
  274. package/templates/storefront/src/modules/skeletons/components/skeleton-order-information/index.tsx +36 -0
  275. package/templates/storefront/src/modules/skeletons/components/skeleton-order-items/index.tsx +43 -0
  276. package/templates/storefront/src/modules/skeletons/components/skeleton-order-summary/index.tsx +15 -0
  277. package/templates/storefront/src/modules/skeletons/components/skeleton-product-preview/index.tsx +15 -0
  278. package/templates/storefront/src/modules/skeletons/templates/skeleton-cart-page/index.tsx +65 -0
  279. package/templates/storefront/src/modules/skeletons/templates/skeleton-order-confirmed/index.tsx +21 -0
  280. package/templates/storefront/src/modules/skeletons/templates/skeleton-product-grid/index.tsx +23 -0
  281. package/templates/storefront/src/modules/skeletons/templates/skeleton-related-products/index.tsx +25 -0
  282. package/templates/storefront/src/modules/store/components/client-paginated-products.tsx +108 -0
  283. package/templates/storefront/src/modules/store/components/mobile-filters/index.tsx +135 -0
  284. package/templates/storefront/src/modules/store/components/pagination/index.tsx +118 -0
  285. package/templates/storefront/src/modules/store/components/product-list-view-tracker/index.tsx +43 -0
  286. package/templates/storefront/src/modules/store/components/refinement-list/index.tsx +299 -0
  287. package/templates/storefront/src/modules/store/components/refinement-list/sort-products/index.tsx +120 -0
  288. package/templates/storefront/src/modules/store/components/store-header/index.tsx +67 -0
  289. package/templates/storefront/src/modules/store/templates/index.tsx +1 -0
  290. package/templates/storefront/src/modules/store/templates/paginated-products.tsx +175 -0
  291. package/templates/storefront/src/modules/wishlist/components/wishlist-item/index.tsx +797 -0
  292. package/templates/storefront/src/modules/wishlist/templates/index.tsx +176 -0
  293. package/templates/storefront/src/storefront.config.ts +12 -0
  294. package/templates/storefront/src/styles/globals.css +326 -0
  295. package/templates/storefront/src/theme/valero/blocks/home/Features/index.tsx +61 -0
  296. package/templates/storefront/src/theme/valero/blocks/home/Hero/index.tsx +102 -0
  297. package/templates/storefront/src/theme/valero/blocks/home/LovedByMoms/index.tsx +407 -0
  298. package/templates/storefront/src/theme/valero/blocks/home/NewArrivals/index.tsx +48 -0
  299. package/templates/storefront/src/theme/valero/blocks/home/ShopByAge/index.tsx +128 -0
  300. package/templates/storefront/src/theme/valero/blocks/home/ShopByCategory/index.tsx +409 -0
  301. package/templates/storefront/src/theme/valero/blocks/home/Testimonials/index.tsx +697 -0
  302. package/templates/storefront/src/theme/valero/blocks/home/WhyChooseUs/index.tsx +62 -0
  303. package/templates/storefront/src/theme/valero/layouts/MainLayoutShell.tsx +14 -0
  304. package/templates/storefront/src/theme/valero/primitives/Button.tsx +28 -0
  305. package/templates/storefront/src/theme/valero/primitives/Card.tsx +32 -0
  306. package/templates/storefront/src/theme/valero/primitives/index.ts +2 -0
  307. package/templates/storefront/src/theme/valero/slots/account/ForgotPassword/index.tsx +1 -0
  308. package/templates/storefront/src/theme/valero/slots/account/Login/index.tsx +1 -0
  309. package/templates/storefront/src/theme/valero/slots/account/LoginTemplate/index.tsx +44 -0
  310. package/templates/storefront/src/theme/valero/slots/account/Register/index.tsx +1 -0
  311. package/templates/storefront/src/theme/valero/slots/cart/CartItem/index.tsx +11 -0
  312. package/templates/storefront/src/theme/valero/slots/cart/CartSummary/index.tsx +13 -0
  313. package/templates/storefront/src/theme/valero/slots/checkout/CheckoutForm/index.tsx +1 -0
  314. package/templates/storefront/src/theme/valero/slots/checkout/CheckoutSummary/index.tsx +1 -0
  315. package/templates/storefront/src/theme/valero/slots/layout/Footer/index.tsx +104 -0
  316. package/templates/storefront/src/theme/valero/slots/layout/Nav/index.tsx +97 -0
  317. package/templates/storefront/src/theme/valero/slots/layout/PromoBar/index.tsx +19 -0
  318. package/templates/storefront/src/theme/valero/slots/layout/PromoBar/promo-bar-content.tsx +174 -0
  319. package/templates/storefront/src/theme/valero/slots/order/OrderDetails/index.tsx +12 -0
  320. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductCTASection.tsx +191 -0
  321. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductDetailsSection.tsx +137 -0
  322. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductFeaturePanel.tsx +245 -0
  323. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductHighlightsSection.tsx +98 -0
  324. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductOptionsSection.tsx +233 -0
  325. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductPriceSection.tsx +53 -0
  326. package/templates/storefront/src/theme/valero/slots/product/ProductActions/ProductTrustSection.tsx +84 -0
  327. package/templates/storefront/src/theme/valero/slots/product/ProductActions/index.tsx +161 -0
  328. package/templates/storefront/src/theme/valero/slots/product/ProductCard/index.tsx +132 -0
  329. package/templates/storefront/src/theme/valero/slots/product/ProductInfo/index.tsx +40 -0
  330. package/templates/storefront/src/theme/valero/templates/StorePage/index.tsx +154 -0
  331. package/templates/storefront/src/theme/valero/tokens/colors.js +16 -0
  332. package/templates/storefront/src/theme/valero/tokens/colors.ts +21 -0
  333. package/templates/storefront/src/theme/valero/tokens/fonts.ts +13 -0
  334. package/templates/storefront/src/theme/valero/tokens/index.ts +3 -0
  335. package/templates/storefront/src/theme/valero/tokens/spacing.ts +9 -0
  336. package/templates/storefront/src/theme/valero/tokens/theme.css +91 -0
  337. package/templates/storefront/tailwind.config.js +221 -0
  338. package/templates/storefront/tsconfig.json +30 -0
@@ -0,0 +1,605 @@
1
+ "use client"
2
+
3
+ import { setAddresses, addCustomerAddressToCart } from "@core/data/cart"
4
+ import compareAddresses from "@core/util/compare-addresses"
5
+ import { CheckCircleSolid } from "@medusajs/icons"
6
+ import { HttpTypes } from "@medusajs/types"
7
+ import { Heading, Text, useToggleState, clx } from "@medusajs/ui"
8
+ import Divider from "@modules/common/components/divider"
9
+ import Spinner from "@modules/common/icons/spinner"
10
+ import { usePathname, useRouter, useSearchParams } from "next/navigation"
11
+ import { useActionState, useState, startTransition, useEffect } from "react"
12
+ import BillingAddress from "../billing_address"
13
+ import ErrorMessage from "../error-message"
14
+ import ShippingAddress from "../shipping-address"
15
+ import { SubmitButton } from "../submit-button"
16
+ import AddressCard from "../address-card"
17
+ import AddAddressModal from "../add-address-modal"
18
+ import SelectAddressModal from "../select-address-modal"
19
+
20
+ const isAddressComplete = (addr: any) => {
21
+ return !!(addr && addr.address_1 && addr.first_name);
22
+ }
23
+
24
+ const Addresses = ({
25
+ cart,
26
+ customer,
27
+ }: {
28
+ cart: HttpTypes.StoreCart | null
29
+ customer: HttpTypes.StoreCustomer | null
30
+ }) => {
31
+ const searchParams = useSearchParams()
32
+ const router = useRouter()
33
+ const pathname = usePathname()
34
+
35
+ const isOnCheckout = pathname.includes("/checkout")
36
+ const step = searchParams.get("step")
37
+ const addressesInRegion = (() => {
38
+ const filtered = customer?.addresses.filter(
39
+ (a) => a.country_code && cart?.region?.countries?.some(c => c.iso_2 === a.country_code)
40
+ ) || []
41
+ // Deduplicate: if two addresses have same address_1 + postal_code + city, keep the newer one
42
+ const seen = new Map<string, typeof filtered[0]>()
43
+ for (const addr of filtered) {
44
+ const key = `${(addr.address_1 || "").trim().toLowerCase()}|${(addr.postal_code || "").trim()}|${(addr.city || "").trim().toLowerCase()}`
45
+ const existing = seen.get(key)
46
+ if (!existing) {
47
+ seen.set(key, addr)
48
+ } else {
49
+ // Keep the more recently updated one, or the default one
50
+ const existingIsDefault = existing.is_default_shipping || existing.metadata?.is_default === "true" || existing.metadata?.is_default === true
51
+ const addrIsDefault = addr.is_default_shipping || addr.metadata?.is_default === "true" || addr.metadata?.is_default === true
52
+ if (addrIsDefault && !existingIsDefault) {
53
+ seen.set(key, addr)
54
+ } else if (!addrIsDefault && !existingIsDefault) {
55
+ const existingTime = new Date(existing.updated_at || 0).getTime()
56
+ const addrTime = new Date(addr.updated_at || 0).getTime()
57
+ if (addrTime > existingTime) seen.set(key, addr)
58
+ }
59
+ }
60
+ }
61
+ return Array.from(seen.values())
62
+ })()
63
+
64
+ const defaultAddress = [...addressesInRegion].sort((a, b) => {
65
+ if (a.is_default_shipping && !b.is_default_shipping) return -1
66
+ if (!a.is_default_shipping && b.is_default_shipping) return 1
67
+ const aDef = a.metadata?.is_default === "true" || a.metadata?.is_default === true
68
+ const bDef = b.metadata?.is_default === "true" || b.metadata?.is_default === true
69
+ if (aDef && !bDef) return -1
70
+ if (!aDef && bDef) return 1
71
+ return new Date(b.updated_at || 0).getTime() - new Date(a.updated_at || 0).getTime()
72
+ })[0]
73
+
74
+ // Determine the initial checkout step based on whether the user has a saved address.
75
+ // • If no address exists → start on the address step.
76
+ // • If an address exists → start on the payment step.
77
+ // • Manual overrides (URL step query) are respected.
78
+ const hasSavedAddress = !!defaultAddress && isAddressComplete(defaultAddress);
79
+ const initialStep = hasSavedAddress ? "payment" : "address";
80
+ const isOpen = (
81
+ step === "address" ||
82
+ step === "payment" ||
83
+ (!step && initialStep === "address")
84
+ );
85
+
86
+ // Scroll to top and ensure URL reflects the derived initial step when no step param is present
87
+ useEffect(() => {
88
+ window.scrollTo({ top: 0, behavior: 'instant' as ScrollBehavior });
89
+ if (!step) {
90
+ router.push(`${pathname}?step=${initialStep}`, { scroll: false });
91
+ }
92
+ }, [step, initialStep, pathname, router]);
93
+
94
+ const { state: sameAsBilling, toggle: toggleSameAsBilling } = useToggleState(
95
+ cart?.shipping_address && cart?.billing_address
96
+ ? compareAddresses(cart?.shipping_address, cart?.billing_address)
97
+ : true
98
+ )
99
+
100
+ /* Edit Mode State */
101
+ const [isEditing, setIsEditing] = useState(false)
102
+
103
+ const handleEdit = () => {
104
+ setIsEditing(true)
105
+ router.push(pathname + "?step=address")
106
+ }
107
+
108
+ const [message, formAction, isPending] = useActionState(setAddresses, null)
109
+
110
+ // Listen for trigger from summary button
111
+ useEffect(() => {
112
+ const handleTrigger = () => {
113
+ const form = document.querySelector('form[autoComplete="off"]') as HTMLFormElement
114
+ const phoneInput = document.getElementById("shipping_phone_field") as HTMLInputElement
115
+
116
+ if (phoneInput) {
117
+ const phoneValue = phoneInput.value.replace(/\D/g, "")
118
+ // For India (+91), expect at least 12 digits (2 for 91, 10 for local)
119
+ if (phoneValue.length < 12) {
120
+ return
121
+ }
122
+ }
123
+
124
+ if (form && !form.checkValidity()) {
125
+ return
126
+ }
127
+
128
+ const submitBtn = document.querySelector('[data-testid="submit-address-button"]') as HTMLButtonElement
129
+ if (submitBtn) {
130
+ submitBtn.click()
131
+ }
132
+ }
133
+
134
+
135
+ if (isOpen) {
136
+ window.addEventListener('trigger-checkout-step', handleTrigger)
137
+ window.addEventListener('submit-address-for-payment', handleTrigger)
138
+ return () => {
139
+ window.removeEventListener('trigger-checkout-step', handleTrigger)
140
+ window.removeEventListener('submit-address-for-payment', handleTrigger)
141
+ }
142
+ }
143
+ }, [isOpen])
144
+
145
+
146
+
147
+ const [addAddressMessage, addAddressAction, isAddAddressPending] = useActionState(addCustomerAddressToCart, null)
148
+ const [showAddModal, setShowAddModal] = useState(false)
149
+ const [showSelectModal, setShowSelectModal] = useState(false)
150
+ const [editingAddress, setEditingAddress] = useState<HttpTypes.StoreCustomerAddress | null>(null)
151
+ const [showAddAddressForm, setShowAddAddressForm] = useState(false)
152
+ const [isManualRemoval, setIsManualRemoval] = useState(false)
153
+ const [hasManuallySelected, setHasManuallySelected] = useState(false)
154
+
155
+ // Load manual selection state from sessionStorage to survive redirects
156
+ useEffect(() => {
157
+ if (typeof window !== "undefined") {
158
+ const manual = sessionStorage.getItem("medusa_address_manual")
159
+ if (manual === "true") {
160
+ setHasManuallySelected(true)
161
+ }
162
+ }
163
+
164
+ // Hande real-time postal code updates for shipping calculation
165
+ const handlePostalUpdate = async (e: any) => {
166
+ const { postal_code, city, province } = e.detail;
167
+
168
+ // Read current form values from DOM using explicit IDs to avoid data loss on refresh
169
+ const fullNameInput = document.getElementById("shipping_full_name_field") as HTMLInputElement
170
+ const address1Input = document.getElementById("shipping_address_1_field") as HTMLInputElement
171
+ const companyInput = document.getElementById("shipping_company_field") as HTMLInputElement
172
+ const phoneInput = document.getElementById("shipping_phone_field_internal") as HTMLInputElement
173
+ const emailInput = document.getElementById("shipping_email_field") as HTMLInputElement
174
+ const cityInput = document.getElementById("shipping_city_field") as HTMLInputElement
175
+ const provinceInput = document.getElementById("shipping_province_field") as HTMLInputElement
176
+
177
+ const full_name = fullNameInput?.value || (cart?.shipping_address?.first_name ? `${cart.shipping_address.first_name} ${cart.shipping_address.last_name === "." ? "" : cart.shipping_address.last_name}`.trim() : "")
178
+ const [first_name, ...last_name_parts] = (full_name || "").split(" ")
179
+ const last_name = last_name_parts.join(" ") || "."
180
+
181
+ const address_1 = address1Input?.value || cart?.shipping_address?.address_1 || ""
182
+ const city_val = city || cityInput?.value || cart?.shipping_address?.city || ""
183
+ const province_val = province || provinceInput?.value || cart?.shipping_address?.province || ""
184
+ const phone = phoneInput?.value || cart?.shipping_address?.phone || ""
185
+ const email = emailInput?.value || cart?.email || ""
186
+ const company = companyInput?.value || cart?.shipping_address?.company || ""
187
+
188
+ // Check if data actually changed to prevent infinite loops
189
+ const currentShipping = cart?.shipping_address
190
+ const hasChanged =
191
+ (postal_code?.trim() || "") !== ((currentShipping?.postal_code as string)?.trim() || "") ||
192
+ (email?.trim().toLowerCase() || "") !== ((cart?.email as string)?.trim().toLowerCase() || "") ||
193
+ (city_val?.trim().toLowerCase() || "") !== ((currentShipping?.city as string)?.trim().toLowerCase() || "") ||
194
+ (province_val?.trim().toLowerCase() || "") !== ((currentShipping?.province as string)?.trim().toLowerCase() || "") ||
195
+ (first_name?.trim().toLowerCase() || "") !== ((currentShipping?.first_name as string)?.trim().toLowerCase() || "") ||
196
+ (last_name?.trim().toLowerCase() || "") !== ((currentShipping?.last_name as string)?.trim().toLowerCase() || "") ||
197
+ (address_1?.trim() || "") !== ((currentShipping?.address_1 as string)?.trim() || "") ||
198
+ (company?.trim() || "") !== ((currentShipping?.company as string)?.trim() || "") ||
199
+ (phone?.replace(/\D/g, "") !== currentShipping?.phone?.replace(/\D/g, ""))
200
+
201
+ if (!hasChanged) return
202
+
203
+ // Add a global lock to prevent double-firing in rapid succession
204
+ if ((window as any).isUpdatingAddress) return;
205
+
206
+ try {
207
+ (window as any).isUpdatingAddress = true;
208
+ // We do a silent update to trigger shipping calculation
209
+ const { updateAddressSilently } = await import("@core/data/cart")
210
+ await updateAddressSilently({
211
+ email: email,
212
+ shipping_address: {
213
+ postal_code,
214
+ city: city_val,
215
+ province: province_val,
216
+ country_code: cart?.shipping_address?.country_code || "in",
217
+ first_name: first_name,
218
+ last_name: last_name,
219
+ address_1: address_1,
220
+ company: company,
221
+ phone: phone
222
+ }
223
+ })
224
+
225
+ // Notify Totals that address is updated on server
226
+ window.dispatchEvent(new CustomEvent('address-updated-silent'))
227
+
228
+ // Trigger a router refresh to update the sidebar totals UI
229
+ router.refresh()
230
+ } finally {
231
+ // Short delay before unlocking
232
+ setTimeout(() => {
233
+ (window as any).isUpdatingAddress = false;
234
+ }, 500);
235
+ }
236
+ }
237
+
238
+ window.addEventListener('postal-code-updated', handlePostalUpdate)
239
+ return () => window.removeEventListener('postal-code-updated', handlePostalUpdate)
240
+ }, [cart, router])
241
+
242
+
243
+
244
+ const shouldAutoSelect = !!defaultAddress && !isEditing && !isManualRemoval && !hasManuallySelected
245
+
246
+ // Auto-select default address if needed
247
+ useEffect(() => {
248
+ if (isOpen && shouldAutoSelect && defaultAddress && !isPending) {
249
+ // If cart has no address, OR if the current address is different from default
250
+ // We trigger the update.
251
+ // Simple check: if we are supposed to auto-select, and we haven't just submitted
252
+ const isAddressMatching = cart?.shipping_address &&
253
+ cart.shipping_address.address_1 === defaultAddress.address_1 &&
254
+ cart.shipping_address.postal_code === defaultAddress.postal_code;
255
+
256
+ if (!isAddressMatching) {
257
+ const formData = new FormData()
258
+ formData.append("shipping_address.first_name", defaultAddress.first_name || "")
259
+ formData.append("shipping_address.last_name", defaultAddress.last_name || "")
260
+ formData.append("shipping_address.address_1", defaultAddress.address_1 || "")
261
+ formData.append("shipping_address.address_2", defaultAddress.address_2 || "")
262
+ formData.append("shipping_address.company", defaultAddress.company || "")
263
+ formData.append("shipping_address.postal_code", defaultAddress.postal_code || "")
264
+ formData.append("shipping_address.city", defaultAddress.city || "")
265
+ formData.append("shipping_address.country_code", defaultAddress.country_code || "")
266
+ formData.append("shipping_address.province", defaultAddress.province || "")
267
+ formData.append("shipping_address.phone", defaultAddress.phone || "")
268
+ formData.append("email", customer?.email || cart?.email || "")
269
+ formData.append("same_as_billing", "on")
270
+
271
+ startTransition(() => {
272
+ formAction(formData)
273
+ })
274
+ }
275
+ }
276
+ }, [isOpen, shouldAutoSelect, cart?.shipping_address, defaultAddress, isPending, formAction, customer?.email, cart?.email])
277
+
278
+ // Find the selected address from cart
279
+ const selectedAddressFromCart = cart?.shipping_address && customer?.addresses.find(a =>
280
+ a.address_1 === cart.shipping_address?.address_1 &&
281
+ a.first_name === cart.shipping_address?.first_name &&
282
+ a.last_name === cart.shipping_address?.last_name
283
+ )
284
+
285
+ const [selectedAddressId, setSelectedAddressId] = useState<string | null>(
286
+ selectedAddressFromCart?.id || (shouldAutoSelect ? defaultAddress?.id : null) || null
287
+ )
288
+
289
+ const handleAddressSelect = (addressId: string) => {
290
+ setSelectedAddressId(addressId)
291
+ }
292
+
293
+ const handleContinue = () => {
294
+ const currentAddressId = selectedAddressId || selectedAddressFromCart?.id
295
+ const address = customer?.addresses.find(a => a.id === currentAddressId)
296
+ if (address && cart) {
297
+ const formData = new FormData()
298
+ formData.append("shipping_address.first_name", address.first_name || "")
299
+ formData.append("shipping_address.last_name", address.last_name || "")
300
+ formData.append("shipping_address.address_1", address.address_1 || "")
301
+ formData.append("shipping_address.address_2", address.address_2 || "")
302
+ formData.append("shipping_address.company", address.company || "")
303
+ formData.append("shipping_address.postal_code", address.postal_code || "")
304
+ formData.append("shipping_address.city", address.city || "")
305
+ formData.append("shipping_address.country_code", address.country_code || "")
306
+ formData.append("shipping_address.province", address.province || "")
307
+ formData.append("shipping_address.phone", address.phone || "")
308
+ formData.append("email", customer?.email || cart?.email || "")
309
+ formData.append("same_as_billing", sameAsBilling ? "on" : "")
310
+
311
+ startTransition(() => {
312
+ formAction(formData)
313
+ })
314
+ } else {
315
+ router.push(pathname + "?step=address")
316
+ }
317
+ }
318
+
319
+
320
+
321
+ // Convert cart address to customer address format for display
322
+ const cartAddressAsCustomerAddress = cart?.shipping_address ? {
323
+ id: selectedAddressFromCart?.id || 'cart-address',
324
+ first_name: cart.shipping_address.first_name || '',
325
+ last_name: cart.shipping_address.last_name === "." ? "" : (cart.shipping_address.last_name || ""),
326
+ address_1: cart.shipping_address.address_1 || '',
327
+ address_2: cart.shipping_address.address_2 || '',
328
+ city: cart.shipping_address.city || '',
329
+ province: cart.shipping_address.province || '',
330
+ postal_code: cart.shipping_address.postal_code || '',
331
+ country_code: cart.shipping_address.country_code || '',
332
+ phone: cart.shipping_address.phone || '',
333
+ metadata: (selectedAddressFromCart as any)?.metadata || { address_type: 'HOME' }
334
+ } : null
335
+
336
+ // Determine which address to display in the summary view to avoid flickering
337
+ // Priority:
338
+ // 1. Current address in cart (if complete)
339
+ // 2. Default address (if we are in auto-select mode)
340
+ // 3. Last fallback
341
+ const addressToDisplay = (cart?.shipping_address && isAddressComplete(cart.shipping_address))
342
+ ? cartAddressAsCustomerAddress
343
+ : (shouldAutoSelect ? defaultAddress : (defaultAddress || cartAddressAsCustomerAddress))
344
+
345
+ return (
346
+ <div className="bg-page-bg">
347
+ {cart && (
348
+ <AddAddressModal
349
+ isOpen={showAddModal}
350
+ onClose={() => {
351
+ setShowAddModal(false)
352
+ setEditingAddress(null)
353
+ }}
354
+ onSave={(formData) => {
355
+ if (typeof window !== "undefined") {
356
+ sessionStorage.setItem("medusa_address_manual", "true")
357
+ }
358
+ setHasManuallySelected(true)
359
+ startTransition(() => {
360
+ addAddressAction(formData)
361
+ setIsManualRemoval(false)
362
+ })
363
+ }}
364
+ cart={cart}
365
+ editingAddress={editingAddress}
366
+ />
367
+ )}
368
+
369
+ {customer && (
370
+ <SelectAddressModal
371
+ isOpen={showSelectModal}
372
+ onClose={() => setShowSelectModal(false)}
373
+ addresses={addressesInRegion}
374
+ selectedAddressId={selectedAddressId}
375
+ onSelect={(id) => {
376
+ handleAddressSelect(id)
377
+ setIsManualRemoval(false)
378
+ if (typeof window !== "undefined") {
379
+ sessionStorage.setItem("medusa_address_manual", "true")
380
+ }
381
+ setHasManuallySelected(true)
382
+ // Trigger address update and continue
383
+ const address = addressesInRegion.find(a => a.id === id)
384
+ if (address && cart) {
385
+ const formData = new FormData()
386
+ formData.append("shipping_address.first_name", address.first_name || "")
387
+ formData.append("shipping_address.last_name", address.last_name || "")
388
+ formData.append("shipping_address.address_1", address.address_1 || "")
389
+ formData.append("shipping_address.address_2", address.address_2 || "")
390
+ formData.append("shipping_address.company", address.company || "")
391
+ formData.append("shipping_address.postal_code", address.postal_code || "")
392
+ formData.append("shipping_address.city", address.city || "")
393
+ formData.append("shipping_address.country_code", address.country_code || "")
394
+ formData.append("shipping_address.province", address.province || "")
395
+ formData.append("shipping_address.phone", address.phone || "")
396
+ formData.append("email", customer?.email || cart?.email || "")
397
+ formData.append("same_as_billing", sameAsBilling ? "on" : "")
398
+
399
+ startTransition(() => {
400
+ formAction(formData)
401
+ })
402
+ }
403
+ }}
404
+ onEdit={(address) => {
405
+ setEditingAddress(address)
406
+ setShowSelectModal(false)
407
+ setShowAddModal(true)
408
+ }}
409
+ />
410
+ )}
411
+
412
+ {isOpen ? (
413
+ <>
414
+ {/* Header */}
415
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-y-4 mb-6">
416
+ <Heading
417
+ level="h2"
418
+ className="text-xl sm:text-2xl font-bold text-heading"
419
+ >
420
+ Enter Delivery Address
421
+ </Heading>
422
+
423
+ <div className="flex flex-row gap-2 sm:gap-3">
424
+ {customer && addressesInRegion.length > 1 && (
425
+ <button
426
+ onClick={() => setShowSelectModal(true)}
427
+ className="px-3 min-[550px]:px-6 py-2 min-[550px]:py-2.5 rounded-full text-[13px] min-[550px]:text-base font-bold whitespace-nowrap shadow-brand-sm checkout-btn-primary"
428
+ >
429
+ Select Address
430
+ </button>
431
+ )}
432
+ {customer && (
433
+ <button
434
+ onClick={() => setShowAddModal(true)}
435
+ className={clx(
436
+ "px-3 min-[550px]:px-6 py-2 min-[550px]:py-2.5 rounded-full text-[13px] min-[550px]:text-base font-bold whitespace-nowrap shadow-brand-sm transition-all",
437
+ addressesInRegion.length > 0
438
+ ? "checkout-btn-primary"
439
+ : "checkout-btn-outline"
440
+ )}
441
+ >
442
+ Add New Address
443
+ </button>
444
+ )}
445
+ </div>
446
+ </div>
447
+
448
+ {/* If we have addresses, show the selected one in a single card, otherwise show the form */}
449
+ {customer && addressesInRegion.length > 0 && !showAddModal && !showAddAddressForm ? (
450
+ <div className="space-y-4">
451
+ {/* Default Address Label */}
452
+ {(addressToDisplay?.id === defaultAddress?.id || (addressToDisplay as any)?.metadata?.is_default === true) && (
453
+ <div className="mb-3">
454
+ <Text className="text-sm uppercase text-gray-400 font-medium">
455
+ DEFAULT ADDRESS
456
+ </Text>
457
+ </div>
458
+ )}
459
+
460
+ <AddressCard
461
+ address={addressToDisplay as any}
462
+ isSelected={true}
463
+ isDefault={addressToDisplay?.id === defaultAddress?.id}
464
+ onSelect={() => setShowSelectModal(true)}
465
+ onEdit={() => {
466
+ setEditingAddress(addressToDisplay as any)
467
+ setShowAddModal(true)
468
+ }}
469
+ onRemove={() => {
470
+ setShowSelectModal(true)
471
+ }}
472
+ />
473
+
474
+ {/* Hidden trigger for programmatic submission */}
475
+ <button
476
+ onClick={handleContinue}
477
+ className="hidden"
478
+ data-testid="submit-address-button"
479
+ />
480
+
481
+ <ErrorMessage error={message} data-testid="address-error-message" />
482
+ </div>
483
+ ) : (
484
+ <form action={formAction} autoComplete="off" noValidate>
485
+ <div className="pb-8">
486
+ <ShippingAddress
487
+ customer={customer}
488
+ checked={sameAsBilling}
489
+ onChange={toggleSameAsBilling}
490
+ cart={cart}
491
+ clearForm={showAddAddressForm}
492
+ />
493
+
494
+ {!sameAsBilling && (
495
+ <div>
496
+ <Heading
497
+ level="h2"
498
+ className="text-3xl-regular gap-x-4 pb-6 pt-8"
499
+ >
500
+ Billing address
501
+ </Heading>
502
+
503
+ <BillingAddress cart={cart} customer={customer} />
504
+ </div>
505
+ )}
506
+ <button
507
+ type="submit"
508
+ className="mt-6 px-6 py-3 bg-gray-900 text-inverse rounded-lg font-medium hover:bg-gray-800 transition-colors hidden"
509
+ data-testid="submit-address-button"
510
+ >
511
+ Continue to delivery
512
+ </button>
513
+ <ErrorMessage error={message} data-testid="address-error-message" />
514
+ </div>
515
+ </form>
516
+ )}
517
+ </>
518
+ ) : (
519
+ <div>
520
+ {/* Header */}
521
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-y-4 mb-6">
522
+ <Heading
523
+ level="h2"
524
+ className="text-xl sm:text-2xl font-bold text-heading"
525
+ >
526
+ Delivery Address
527
+ </Heading>
528
+ {!isManualRemoval && customer && (
529
+ <div className="flex flex-row gap-2 sm:gap-3">
530
+ {customer && addressesInRegion.length > 1 && (
531
+ <button
532
+ onClick={() => setShowSelectModal(true)}
533
+ className="px-3 min-[550px]:px-6 py-2 min-[550px]:py-2.5 rounded-full text-[13px] min-[550px]:text-base font-bold whitespace-nowrap shadow-brand-sm checkout-btn-primary"
534
+ >
535
+ Select Address
536
+ </button>
537
+ )}
538
+ <button
539
+ onClick={() => setShowAddModal(true)}
540
+ className="px-3 min-[550px]:px-6 py-2 min-[550px]:py-2.5 rounded-full text-[13px] min-[550px]:text-base font-bold whitespace-nowrap shadow-brand-sm checkout-btn-primary"
541
+ data-testid="add-new-address-button"
542
+ >
543
+ Add New Address
544
+ </button>
545
+ </div>
546
+ )}
547
+ </div>
548
+
549
+ {addressToDisplay && !isManualRemoval ? (
550
+ <div className="space-y-4">
551
+ {/* Default Address Label */}
552
+ {(addressToDisplay.id === defaultAddress?.id || (addressToDisplay as any)?.metadata?.is_default === true) && (
553
+ <div className="mb-3">
554
+ <Text className="text-sm uppercase text-gray-400 font-medium">
555
+ DEFAULT ADDRESS
556
+ </Text>
557
+ </div>
558
+ )}
559
+
560
+ <AddressCard
561
+ address={addressToDisplay as any}
562
+ isSelected={true}
563
+ isDefault={addressToDisplay.id === defaultAddress?.id}
564
+ onSelect={() => handleEdit()}
565
+ onEdit={() => {
566
+ setEditingAddress(addressToDisplay as any)
567
+ setShowAddModal(true)
568
+ }}
569
+ onRemove={() => {
570
+ setShowSelectModal(true)
571
+ }}
572
+ />
573
+ </div>
574
+ ) : (addressToDisplay || isManualRemoval) ? (
575
+ <div className="flex flex-col min-[550px]:flex-row gap-4 mt-4">
576
+ {customer && (
577
+ <button
578
+ onClick={() => setShowAddModal(true)}
579
+ className="flex-1 px-6 py-3 rounded-full font-bold checkout-btn-primary shadow-brand-sm"
580
+ >
581
+ Add New Address
582
+ </button>
583
+ )}
584
+ {customer && addressesInRegion.length > 1 && (
585
+ <button
586
+ onClick={() => setShowSelectModal(true)}
587
+ className="flex-1 px-6 py-3 rounded-full font-bold checkout-btn-outline"
588
+ >
589
+ Select Address
590
+ </button>
591
+ )}
592
+ </div>
593
+ ) : (
594
+ <div>
595
+ <Spinner />
596
+ </div>
597
+ )}
598
+ </div>
599
+ )}
600
+ <Divider className="mt-8" />
601
+ </div>
602
+ )
603
+ }
604
+
605
+ export default Addresses
@@ -0,0 +1,32 @@
1
+ "use client"
2
+
3
+ import LocalizedClientLink from "@modules/common/components/localized-client-link"
4
+ import ChevronDown from "@modules/common/icons/chevron-down"
5
+ import { usePathname } from "next/navigation"
6
+
7
+ export default function BackLink() {
8
+ const pathname = usePathname()
9
+ const isOnPaymentPage = pathname.includes("/checkout/payment")
10
+
11
+ // LocalizedClientLink will handle country code automatically
12
+ // So we just need to provide the path without country code
13
+ const backHref = isOnPaymentPage ? "/checkout" : "/cart"
14
+ const backText = isOnPaymentPage ? "Back to checkout" : "Back to shopping cart"
15
+
16
+ return (
17
+ <LocalizedClientLink
18
+ href={backHref}
19
+ className="text-small-semi text-ui-fg-base flex items-center gap-x-2 uppercase flex-1 basis-0"
20
+ data-testid="back-to-cart-link"
21
+ >
22
+ <ChevronDown className="rotate-90" size={16} />
23
+ <span className="mt-px hidden small:block txt-compact-plus text-ui-fg-subtle hover:text-ui-fg-base ">
24
+ {backText}
25
+ </span>
26
+ <span className="mt-px block small:hidden txt-compact-plus text-ui-fg-subtle hover:text-ui-fg-base">
27
+ Back
28
+ </span>
29
+ </LocalizedClientLink>
30
+ )
31
+ }
32
+