@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,333 @@
1
+ "use client"
2
+
3
+ import { useState, useRef } from "react"
4
+ import { retrieveCustomer, uploadFiles } from "@core/data/customer"
5
+ import { submitReview, updateReview } from "@core/data/reviews"
6
+
7
+ type ReviewModalProps = {
8
+ productId: string
9
+ productTitle: string
10
+ isOpen: boolean
11
+ close: () => void
12
+ existingReview?: any // Optional
13
+ onSuccess?: () => void // Optional callback for refetching
14
+ }
15
+
16
+ export default function ReviewModal({
17
+ productId,
18
+ productTitle,
19
+ isOpen,
20
+ close,
21
+ existingReview,
22
+ onSuccess,
23
+ }: ReviewModalProps) {
24
+ const [rating, setRating] = useState(existingReview?.rating || 0)
25
+ const [title, setTitle] = useState(existingReview?.title || "")
26
+ const [description, setDescription] = useState(existingReview?.description || "")
27
+ const [isSubmitting, setIsSubmitting] = useState(false)
28
+ const [images, setImages] = useState<string[]>(existingReview?.images || [])
29
+ const [isUploading, setIsUploading] = useState(false)
30
+ const [isSubmitted, setIsSubmitted] = useState(false)
31
+ const [error, setError] = useState<string | null>(null)
32
+ const modalRef = useRef<HTMLDivElement>(null)
33
+ const fileInputRef = useRef<HTMLInputElement>(null)
34
+
35
+ // Close on outside click
36
+ const handleBackdropClick = (e: React.MouseEvent) => {
37
+ if (modalRef.current && !modalRef.current.contains(e.target as Node)) {
38
+ handleClose()
39
+ }
40
+ }
41
+
42
+ const handleClose = () => {
43
+ close()
44
+ // Reset state after a tiny delay to allow exit animation if needed
45
+ setTimeout(() => {
46
+ setIsSubmitted(false)
47
+ setError(null)
48
+ }, 300)
49
+ }
50
+
51
+ if (!isOpen) return null
52
+
53
+ const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
54
+ const files = e.target.files
55
+ if (!files || files.length === 0) return
56
+
57
+ setIsUploading(true)
58
+ setError(null)
59
+ try {
60
+ const formData = new FormData()
61
+ for (let i = 0; i < files.length; i++) {
62
+ if (files[i].size > 5 * 1024 * 1024) {
63
+ setError("Please upload images smaller than 5MB.")
64
+ setIsUploading(false)
65
+ return
66
+ }
67
+ formData.append("files", files[i])
68
+ }
69
+
70
+ const result = await uploadFiles(formData)
71
+ if (result.success && result.files) {
72
+ const newImageUrls = result.files.map((f: any) => f.url)
73
+ setImages((prev) => [...prev, ...newImageUrls].slice(0, 4)) // Limit to 4 images
74
+ } else {
75
+ setError(result.error || "Failed to upload images")
76
+ }
77
+ } catch (error) {
78
+ setError("An error occurred during upload")
79
+ } finally {
80
+ setIsUploading(false)
81
+ }
82
+ }
83
+
84
+ const removeImage = (index: number) => {
85
+ setImages((prev) => prev.filter((_, i) => i !== index))
86
+ }
87
+
88
+ const handleSubmit = async (e: React.FormEvent) => {
89
+ e.preventDefault()
90
+ setIsSubmitting(true)
91
+ setError(null)
92
+
93
+ if (rating === 0) {
94
+ setError("Please select a rating before submitting.")
95
+ setIsSubmitting(false)
96
+ return
97
+ }
98
+
99
+ try {
100
+ const customer = await retrieveCustomer()
101
+
102
+ if (!customer) {
103
+ setError("Please login to submit a review.")
104
+ setIsSubmitting(false)
105
+ return
106
+ }
107
+
108
+ let result;
109
+
110
+ if (existingReview?.id) {
111
+ // Update existing review
112
+ result = await updateReview({
113
+ id: existingReview.id,
114
+ rating,
115
+ title,
116
+ description,
117
+ images: images,
118
+ })
119
+ } else {
120
+ // Submit new review
121
+ result = await submitReview({
122
+ product_id: productId,
123
+ rating,
124
+ title,
125
+ description,
126
+ images: images,
127
+ })
128
+ }
129
+
130
+ if (result.success) {
131
+ // Track form submission in Google Analytics
132
+ if (typeof window !== 'undefined') {
133
+ (window as any).dataLayer = (window as any).dataLayer || [];
134
+ (window as any).dataLayer.push({
135
+ event: 'form_submit',
136
+ form_type: existingReview ? 'product_review_update' : 'product_review_submit'
137
+ });
138
+ }
139
+
140
+ setIsSubmitted(true)
141
+ setTitle("")
142
+ setDescription("")
143
+ setRating(0)
144
+ setImages([])
145
+
146
+ // Auto close modal after 1.5 seconds
147
+ setTimeout(() => {
148
+ handleClose()
149
+ if (onSuccess) onSuccess()
150
+ }, 1500)
151
+ } else {
152
+ setError(result.error || "Failed to submit review")
153
+ }
154
+ } catch (error) {
155
+ setError("An error occurred. Please try again.")
156
+ } finally {
157
+ setIsSubmitting(false)
158
+ }
159
+ }
160
+
161
+ return (
162
+ <div
163
+ className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
164
+ onClick={handleBackdropClick}
165
+ >
166
+ <div
167
+ ref={modalRef}
168
+ className="bg-white rounded-xl shadow-2xl w-full max-w-md overflow-hidden animate-in fade-in zoom-in duration-200"
169
+ >
170
+ <div className="bg-[#8B5AB1] p-4 text-white flex justify-between items-center">
171
+ <h2 className="text-xl font-bold">
172
+ {isSubmitted ? (existingReview ? "Update Successful" : "Review Submitted") : existingReview ? "Edit Review" : "Write a Review"}
173
+ </h2>
174
+ <button onClick={handleClose} className="text-white hover:text-gray-200">
175
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
176
+ <line x1="18" y1="6" x2="6" y2="18"></line>
177
+ <line x1="6" y1="6" x2="18" y2="18"></line>
178
+ </svg>
179
+ </button>
180
+ </div>
181
+
182
+ {isSubmitted ? (
183
+ <div className="p-8 text-center space-y-4 animate-in fade-in slide-in-from-bottom-4 duration-300">
184
+ <div className="flex justify-center">
185
+ <div className="bg-green-100 rounded-full p-4 text-green-600">
186
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3">
187
+ <polyline points="20 6 9 17 4 12"></polyline>
188
+ </svg>
189
+ </div>
190
+ </div>
191
+ <div>
192
+ <h3 className="text-2xl font-bold text-gray-900 mb-2">Thank You!</h3>
193
+ <p className="text-gray-600">
194
+ Your review for <span className="font-semibold">{productTitle}</span> has been {existingReview ? "updated" : "submitted"} successfully.
195
+ </p>
196
+ </div>
197
+ <button
198
+ onClick={handleClose}
199
+ className="w-full bg-[#8B5AB1] text-white font-bold py-3 px-4 rounded-lg hover:bg-[#7a4a9a] active:bg-[#693e84] transition-colors shadow-md hover:shadow-lg transform active:scale-[0.98]"
200
+ >
201
+ Close
202
+ </button>
203
+ </div>
204
+ ) : (
205
+ <form onSubmit={handleSubmit} className="p-6 space-y-4 max-h-[80vh] overflow-y-auto no-scrollbar">
206
+ <div>
207
+ <label className="block text-sm font-medium text-gray-700 mb-1">Product</label>
208
+ <p className="text-gray-900 font-medium">{productTitle}</p>
209
+ </div>
210
+
211
+ <div>
212
+ <label className="block text-sm font-medium text-gray-700 mb-1">Rating</label>
213
+ <div className="flex gap-1">
214
+ {[1, 2, 3, 4, 5].map((star) => (
215
+ <button
216
+ key={star}
217
+ type="button"
218
+ onClick={() => setRating(star)}
219
+ className="focus:outline-none transition-transform hover:scale-110"
220
+ >
221
+ <svg
222
+ width="32"
223
+ height="32"
224
+ viewBox="0 0 24 24"
225
+ fill={star <= rating ? "#FFD700" : "none"}
226
+ stroke={star <= rating ? "#FFD700" : "#D1D5DB"}
227
+ strokeWidth="2"
228
+ >
229
+ <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
230
+ </svg>
231
+ </button>
232
+ ))}
233
+ </div>
234
+ </div>
235
+
236
+ <div>
237
+ <label className="block text-sm font-medium text-gray-700 mb-1">Title</label>
238
+ <input
239
+ type="text"
240
+ required
241
+ value={title}
242
+ onChange={(e) => setTitle(e.target.value)}
243
+ className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none transition-all"
244
+ placeholder="Great product!"
245
+ />
246
+ </div>
247
+
248
+ <div>
249
+ <label className="block text-sm font-medium text-gray-700 mb-1">Review</label>
250
+ <textarea
251
+ required
252
+ value={description}
253
+ onChange={(e) => setDescription(e.target.value)}
254
+ rows={4}
255
+ className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none transition-all resize-none"
256
+ placeholder="Share your experience..."
257
+ />
258
+ </div>
259
+
260
+ {/* Image Upload Section */}
261
+ <div>
262
+ <label className="block text-sm font-medium text-gray-700 mb-2">Images (Max 4)</label>
263
+ <div className="flex flex-wrap gap-2 mb-2">
264
+ {images.map((url, index) => (
265
+ <div key={index} className="relative w-20 h-20 rounded-lg overflow-hidden border border-gray-200">
266
+ <img src={url} alt="Review" className="w-full h-full object-cover" />
267
+ <button
268
+ type="button"
269
+ onClick={() => removeImage(index)}
270
+ className="absolute top-1 right-1 bg-red-500 text-white rounded-full p-0.5 hover:bg-red-600 shadow-md"
271
+ >
272
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3">
273
+ <line x1="18" y1="6" x2="6" y2="18"></line>
274
+ <line x1="6" y1="6" x2="18" y2="18"></line>
275
+ </svg>
276
+ </button>
277
+ </div>
278
+ ))}
279
+ {images.length < 4 && (
280
+ <button
281
+ type="button"
282
+ onClick={() => fileInputRef.current?.click()}
283
+ disabled={isUploading}
284
+ className="w-20 h-20 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center text-gray-400 hover:border-[#8B5AB1] hover:text-[#8B5AB1] transition-all"
285
+ >
286
+ {isUploading ? (
287
+ <div className="w-5 h-5 border-2 border-current border-t-transparent rounded-full animate-spin"></div>
288
+ ) : (
289
+ <>
290
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
291
+ <line x1="12" y1="5" x2="12" y2="19"></line>
292
+ <line x1="5" y1="12" x2="19" y2="12"></line>
293
+ </svg>
294
+ <span className="text-[10px] mt-1 font-medium">Add Photo</span>
295
+ </>
296
+ )}
297
+ </button>
298
+ )}
299
+ </div>
300
+ <p className="text-[10px] text-gray-400 mt-1 font-medium">Please upload images smaller than 5MB.</p>
301
+ <input
302
+ ref={fileInputRef}
303
+ type="file"
304
+ accept="image/*"
305
+ multiple
306
+ onChange={handleImageUpload}
307
+ className="hidden"
308
+ />
309
+ </div>
310
+
311
+ {error && (
312
+ <div className="p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm font-medium animate-in fade-in slide-in-from-top-1 duration-200">
313
+ {error}
314
+ </div>
315
+ )}
316
+
317
+ <button
318
+ type="submit"
319
+ disabled={isSubmitting || isUploading}
320
+ data-ga-event={existingReview ? "review_update" : "review_submit"}
321
+ data-ga-label={existingReview ? "Update Review" : "Submit Review"}
322
+ className="w-full bg-[#8B5AB1] text-white font-bold py-3 px-4 rounded-lg hover:bg-[#7a4a9a] active:bg-[#693e84] transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-md hover:shadow-lg transform active:scale-[0.98]"
323
+ >
324
+ <span className="pointer-events-none block">
325
+ {isSubmitting ? "Submitting..." : existingReview ? "Update Review" : "Submit Review"}
326
+ </span>
327
+ </button>
328
+ </form>
329
+ )}
330
+ </div>
331
+ </div>
332
+ )
333
+ }
@@ -0,0 +1,227 @@
1
+ "use client"
2
+
3
+ import React, { useState, useEffect } from "react"
4
+ import { useParams } from "next/navigation"
5
+
6
+ type ShareButtonProps = {
7
+ productTitle: string
8
+ productHandle: string
9
+ }
10
+
11
+ export default function ShareButton({ productTitle, productHandle }: ShareButtonProps) {
12
+ const { countryCode } = useParams() as { countryCode: string }
13
+ const [isOpen, setIsOpen] = useState(false)
14
+ const [copied, setCopied] = useState(false)
15
+
16
+ const productUrl = typeof window !== "undefined"
17
+ ? `${window.location.origin}/${countryCode}/products/${productHandle}`
18
+ : ""
19
+
20
+ const socialLinks = [
21
+ {
22
+ name: "WhatsApp",
23
+ icon: (
24
+ <svg viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6">
25
+ <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.414 0 .018 5.396.015 12.03c0 2.12.553 4.189 1.606 6.06L0 24l6.104-1.599a11.82 11.82 0 005.94 1.59h.005c6.634 0 12.032-5.396 12.035-12.03.001-3.213-1.252-6.234-3.528-8.511z" />
26
+ </svg>
27
+ ),
28
+ url: `https://api.whatsapp.com/send?text=${encodeURIComponent(`Check this out: ${productTitle}\n\n${productUrl}`)}`,
29
+ color: "#25D366"
30
+ },
31
+ {
32
+ name: "Facebook",
33
+ icon: (
34
+ <svg viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6">
35
+ <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" />
36
+ </svg>
37
+ ),
38
+ url: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(productUrl)}`,
39
+ color: "#1877F2"
40
+ },
41
+ {
42
+ name: "Instagram",
43
+ icon: (
44
+ <img
45
+ src="https://upload.wikimedia.org/wikipedia/commons/e/e7/Instagram_logo_2016.svg"
46
+ alt="Instagram"
47
+ className="w-7 h-7 object-contain"
48
+ />
49
+ ),
50
+ url: `https://www.instagram.com/`,
51
+ color: "#E4405F",
52
+ gradient: "linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%)"
53
+ },
54
+ {
55
+ name: "Twitter",
56
+ icon: (
57
+ <svg viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6">
58
+ <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
59
+ </svg>
60
+ ),
61
+ url: `https://twitter.com/intent/tweet?url=${encodeURIComponent(productUrl)}&text=${encodeURIComponent(`Check out ${productTitle}`)}`,
62
+ color: "#000000"
63
+ },
64
+ {
65
+ name: "Telegram",
66
+ icon: (
67
+ <svg viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6 ml-0.5">
68
+ <path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221l-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.446 1.394c-.14.14-.26.26-.53.26l.213-3.05 5.56-5.022c.24-.213-.054-.334-.373-.121l-6.869 4.326-2.96-.924c-.64-.203-.658-.64.135-.954l11.566-4.458c.538-.196 1.006.128.832.941z" />
69
+ </svg>
70
+ ),
71
+ url: `https://t.me/share/url?url=${encodeURIComponent(productUrl)}&text=${encodeURIComponent(`Check out ${productTitle}`)}`,
72
+ color: "#26A5E4"
73
+ }
74
+ ]
75
+
76
+ const copyToClipboard = () => {
77
+ navigator.clipboard.writeText(productUrl)
78
+ setCopied(true)
79
+ setTimeout(() => setCopied(false), 2000)
80
+ }
81
+
82
+ // Prevent scroll when modal is open
83
+ useEffect(() => {
84
+ if (isOpen) {
85
+ document.body.style.overflow = "hidden"
86
+ } else {
87
+ document.body.style.overflow = "unset"
88
+ }
89
+ return () => {
90
+ document.body.style.overflow = "unset"
91
+ }
92
+ }, [isOpen])
93
+
94
+ return (
95
+ <>
96
+ {/* Share Trigger Button - Updated to match uploaded image */}
97
+ <button
98
+ onClick={() => setIsOpen(true)}
99
+ data-ga-event="product_share_open"
100
+ data-ga-label={productTitle}
101
+ className="flex items-center gap-2 text-[#8B5AB1] transition-all duration-300 py-1.5 px-0 rounded-md flex-shrink-0 group bg-transparent hover:text-[#7a4a9a] active:scale-95"
102
+ title="Share"
103
+ >
104
+ <svg
105
+ width="20"
106
+ height="20"
107
+ viewBox="0 0 24 24"
108
+ fill="none"
109
+ stroke="currentColor"
110
+ strokeWidth="2.5"
111
+ strokeLinecap="round"
112
+ strokeLinejoin="round"
113
+ className="w-5 h-5 transition-transform group-hover:scale-110"
114
+ >
115
+ <circle cx="18" cy="5" r="3" />
116
+ <circle cx="6" cy="12" r="3" />
117
+ <circle cx="18" cy="19" r="3" />
118
+ <line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
119
+ <line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
120
+ </svg>
121
+ <span className="text-sm font-semibold tracking-tight">Share</span>
122
+ </button>
123
+
124
+ {/* Modern Center Popup Modal */}
125
+ {isOpen && (
126
+ <div className="fixed inset-0 z-[999] flex items-center justify-center p-2 sm:p-4">
127
+ {/* Simple Dark Blur Backdrop */}
128
+ <div
129
+ className="absolute inset-0 bg-black/20 backdrop-blur-md"
130
+ onClick={() => setIsOpen(false)}
131
+ />
132
+
133
+ {/* Modal Content - No Animation */}
134
+ <div className="relative w-full max-w-[420px] bg-white rounded-[24px] sm:rounded-[32px] shadow-[0_32px_80px_-20px_rgba(0,0,0,0.3)] border border-white/20 overflow-hidden">
135
+
136
+ {/* Modal Header */}
137
+ <div className="p-4 sm:p-6 pb-2 sm:pb-4 flex items-center justify-between">
138
+ <div>
139
+ <h3 className="text-lg sm:text-xl font-bold text-gray-900 leading-none mb-1">Spread the Joy</h3>
140
+ <p className="text-[10px] sm:text-xs text-gray-400 font-medium tracking-tight">Tell your friends about Chocomelon</p>
141
+ </div>
142
+ <button
143
+ onClick={() => setIsOpen(false)}
144
+ className="w-8 h-8 sm:w-10 sm:h-10 flex items-center justify-center rounded-full bg-gray-50 hover:bg-gray-100 text-gray-400 hover:text-gray-900 transition-all active:scale-90"
145
+ >
146
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
147
+ <path d="M18 6L6 18M6 6l12 12" strokeLinecap="round" strokeLinejoin="round" />
148
+ </svg>
149
+ </button>
150
+ </div>
151
+
152
+ {/* Social Sharing Grid */}
153
+ <div className="px-4 sm:px-6 py-4 sm:py-6 grid grid-cols-5 gap-2 sm:gap-4">
154
+ {socialLinks.map((social) => (
155
+ <a
156
+ key={social.name}
157
+ href={social.url}
158
+ target="_blank"
159
+ rel="noopener noreferrer"
160
+ data-ga-event="product_share_click"
161
+ data-ga-label={`${social.name} - ${productTitle}`}
162
+ className="flex flex-col items-center gap-1.5 group outline-none"
163
+ >
164
+ <div
165
+ className="w-10 h-10 min-[360px]:w-11 min-[360px]:h-11 sm:w-14 sm:h-14 rounded-[12px] min-[360px]:rounded-[16px] sm:rounded-[20px] flex items-center justify-center text-white transition-all duration-300 group-hover:scale-110 group-active:scale-95 shadow-lg"
166
+ style={{
167
+ background: (social as any).gradient || social.color,
168
+ boxShadow: `0 8px 16px -4px ${social.color}40`
169
+ }}
170
+ >
171
+ <div className="scale-75 sm:scale-100 flex items-center justify-center">
172
+ {social.icon}
173
+ </div>
174
+ </div>
175
+ <span className="text-[9px] sm:text-[11px] font-bold text-gray-500 group-hover:text-[#8B5AB1] transition-colors truncate w-full text-center">{social.name}</span>
176
+ </a>
177
+ ))}
178
+ </div>
179
+
180
+ {/* Link Copy Section */}
181
+ <div className="px-6 pb-6">
182
+ <div className="bg-gray-50/80 rounded-[24px] p-3.5 border border-gray-100 group transition-all hover:bg-white hover:shadow-inner">
183
+ <div className="flex items-center justify-between mb-2">
184
+ <span className="text-[10px] font-bold text-gray-400 uppercase tracking-widest">Shareable Link</span>
185
+ {copied && (
186
+ <span className="text-[10px] font-bold text-green-500 animate-in fade-in slide-in-from-right-2">Link Copied!</span>
187
+ )}
188
+ </div>
189
+ <div className="flex items-center gap-3">
190
+ <div className="flex-1 overflow-hidden">
191
+ <p className="text-xs text-gray-600 truncate font-semibold">{productUrl}</p>
192
+ </div>
193
+ <button
194
+ onClick={() => {
195
+ copyToClipboard();
196
+ // Handle manual event push for clipboard
197
+ if (typeof window !== 'undefined' && (window as any).gtag) {
198
+ (window as any).gtag('event', 'product_share_click', {
199
+ event_category: 'engagement',
200
+ event_label: `Copy Link - ${productTitle}`
201
+ });
202
+ }
203
+ }}
204
+ className={`h-9 px-4 rounded-[14px] text-xs font-bold transition-all active:scale-95 shadow-md ${copied
205
+ ? 'bg-green-500 text-white shadow-green-100'
206
+ : 'bg-[#8B5AB1] text-white hover:bg-[#7a4a9a] shadow-purple-100'
207
+ }`}
208
+ >
209
+ {copied ? "Done" : "Copy"}
210
+ </button>
211
+ </div>
212
+ </div>
213
+ </div>
214
+
215
+ {/* Brand Footer Decoration */}
216
+ <div className="h-2 w-full flex">
217
+ <div className="flex-1 bg-pink-400"></div>
218
+ <div className="flex-1 bg-yellow-400"></div>
219
+ <div className="flex-1 bg-blue-400"></div>
220
+ <div className="flex-1 bg-purple-500"></div>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ )}
225
+ </>
226
+ )
227
+ }
@@ -0,0 +1,46 @@
1
+ "use client"
2
+ import { useState } from "react"
3
+ import { useWishlist } from "@core/context/wishlist-context"
4
+ import LoginPopup from "@modules/common/components/login-popup"
5
+
6
+ const WishlistIcon = ({ productId }: { productId: string }) => {
7
+ const { isWishlisted, toggleWishlist } = useWishlist()
8
+ const [isToggling, setIsToggling] = useState(false)
9
+ const [showLogin, setShowLogin] = useState(false)
10
+
11
+ const wishlisted = isWishlisted(productId)
12
+
13
+ const handleToggle = async () => {
14
+ setIsToggling(true)
15
+ const res = await toggleWishlist(productId)
16
+ if (!res.success && res.error?.toLowerCase().includes("login")) {
17
+ setShowLogin(true)
18
+ }
19
+ setIsToggling(false)
20
+ }
21
+
22
+ return (
23
+ <>
24
+ <button
25
+ onClick={handleToggle}
26
+ disabled={isToggling}
27
+ className="p-2 rounded-full hover:bg-gray-100 transition-colors flex items-center justify-center gap-1.5"
28
+ aria-label="Wishlist"
29
+ >
30
+ <svg
31
+ width="20"
32
+ height="20"
33
+ viewBox="0 0 24 24"
34
+ fill={wishlisted ? "#ef4444" : "none"}
35
+ stroke={wishlisted ? "#ef4444" : "#4A5568"}
36
+ strokeWidth="2"
37
+ className={isToggling ? "animate-pulse" : "hover:scale-110 transition-transform"}
38
+ >
39
+ <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
40
+ </svg>
41
+ </button>
42
+ {showLogin && <LoginPopup isOpen={showLogin} onClose={() => setShowLogin(false)} />}
43
+ </>
44
+ )
45
+ }
46
+ export default WishlistIcon
@@ -0,0 +1,27 @@
1
+ const Radio = ({ checked, 'data-testid': dataTestId }: { checked: boolean, 'data-testid'?: string }) => {
2
+ return (
3
+ <>
4
+ <button
5
+ type="button"
6
+ role="radio"
7
+ aria-checked="true"
8
+ data-state={checked ? "checked" : "unchecked"}
9
+ className="group relative flex h-5 w-5 items-center justify-center outline-none"
10
+ data-testid={dataTestId || 'radio-button'}
11
+ >
12
+ <div className="shadow-borders-base group-hover:shadow-borders-strong-with-shadow bg-ui-bg-base group-data-[state=checked]:bg-ui-bg-interactive group-data-[state=checked]:shadow-borders-interactive group-focus:!shadow-borders-interactive-with-focus group-disabled:!bg-ui-bg-disabled group-disabled:!shadow-borders-base flex h-[14px] w-[14px] items-center justify-center rounded-full transition-all">
13
+ {checked && (
14
+ <span
15
+ data-state={checked ? "checked" : "unchecked"}
16
+ className="group flex items-center justify-center"
17
+ >
18
+ <div className="bg-ui-bg-base shadow-details-contrast-on-bg-interactive group-disabled:bg-ui-fg-disabled rounded-full group-disabled:shadow-none h-1.5 w-1.5"></div>
19
+ </span>
20
+ )}
21
+ </div>
22
+ </button>
23
+ </>
24
+ )
25
+ }
26
+
27
+ export default Radio