storefront-layouts 1.0.3 → 1.0.4

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 (509) hide show
  1. package/dist/components/auth/LoginForm.js +2 -2
  2. package/dist/components/auth/LoginSheet.js +2 -2
  3. package/dist/components/auth/login-form-core.js +3 -3
  4. package/dist/components/auth/login-sheet-header.js +3 -3
  5. package/dist/components/auth/login-sheet-registry.js +2 -2
  6. package/dist/components/auth/login-sheet-themes/booking-agenda.theme.js +1 -1
  7. package/dist/components/auth/login-sheet-themes/booking.theme.js +1 -1
  8. package/dist/components/auth/login-sheet-themes/clothing-minimal.theme.js +1 -1
  9. package/dist/components/auth/login-sheet-themes/clothing.theme.js +1 -1
  10. package/dist/components/auth/login-sheet-themes/electronics-grid.theme.js +1 -1
  11. package/dist/components/auth/login-sheet-themes/electronics.theme.js +1 -1
  12. package/dist/components/auth/login-sheet-themes/food-modern.theme.js +1 -1
  13. package/dist/components/auth/login-sheet-themes/food.theme.js +1 -1
  14. package/dist/components/auth/login-sheet-themes/index.js +9 -9
  15. package/dist/components/auth/login-sheet-themes/motivational-speaker.theme.js +1 -1
  16. package/dist/components/auth/login-sheet-themes/theme-input-baselines.d.ts +2 -2
  17. package/dist/components/auth/login-sheet-themes/theme-input-baselines.d.ts.map +1 -1
  18. package/dist/components/auth/login-sheet-themes/theme-input-baselines.js +2 -2
  19. package/dist/components/auth/login-sheets/StoreLoginSheetShell.d.ts.map +1 -1
  20. package/dist/components/auth/login-sheets/StoreLoginSheetShell.js +6 -6
  21. package/dist/components/auth/use-login-submit.js +3 -3
  22. package/dist/components/cart/InventoryHoldCountdown.js +2 -2
  23. package/dist/components/categories/category-masonry-grid.js +3 -3
  24. package/dist/components/checkout/CheckoutFeeLines.js +1 -1
  25. package/dist/components/checkout/ShippingOptionsPanel.js +3 -3
  26. package/dist/components/learning/CertificateTemplates.js +2 -2
  27. package/dist/components/learning/CertificateViewer.js +3 -3
  28. package/dist/components/learning/MentorshipProgress.d.ts.map +1 -1
  29. package/dist/components/learning/MentorshipProgress.js +4 -4
  30. package/dist/components/product/ProductVariationSelectors.js +1 -1
  31. package/dist/components/rich-text/CategoryDescription.js +2 -2
  32. package/dist/components/rich-text/ProductDescription.js +2 -2
  33. package/dist/components/rich-text/RichTextExcerpt.js +1 -1
  34. package/dist/components/rich-text/SafeRichHtml.d.ts +8 -11
  35. package/dist/components/rich-text/SafeRichHtml.d.ts.map +1 -1
  36. package/dist/components/rich-text/SafeRichHtml.js +3 -5
  37. package/dist/components/shipping/ProductDeliveryInfoSection.d.ts.map +1 -1
  38. package/dist/components/shipping/ProductDeliveryInfoSection.js +7 -4
  39. package/dist/components/shipping/ShippingQuoteAddressForm.js +3 -3
  40. package/dist/components/ui/alert-modal.js +2 -2
  41. package/dist/components/ui/avatar-image.js +1 -1
  42. package/dist/components/ui/badge.js +1 -1
  43. package/dist/components/ui/breadcrumbs.js +1 -1
  44. package/dist/components/ui/button.d.ts +1 -1
  45. package/dist/components/ui/button.js +1 -1
  46. package/dist/components/ui/card.js +1 -1
  47. package/dist/components/ui/category-tree.js +2 -2
  48. package/dist/components/ui/checkout-button.d.ts.map +1 -1
  49. package/dist/components/ui/checkout-button.js +11 -283
  50. package/dist/components/ui/guest-checkout-modal.js +3 -3
  51. package/dist/components/ui/image-skeleton.js +2 -2
  52. package/dist/components/ui/image-with-fallback.d.ts +3 -1
  53. package/dist/components/ui/image-with-fallback.d.ts.map +1 -1
  54. package/dist/components/ui/image-with-fallback.js +55 -139
  55. package/dist/components/ui/input.js +1 -1
  56. package/dist/components/ui/limited-time-offer-badge.js +2 -2
  57. package/dist/components/ui/loading-skeleton-wrapper.js +1 -1
  58. package/dist/components/ui/modal.js +2 -2
  59. package/dist/components/ui/otp-input.js +1 -1
  60. package/dist/components/ui/out-of-stock-overlay.js +1 -1
  61. package/dist/components/ui/page-animate-wrapper.js +2 -2
  62. package/dist/components/ui/page-content-loader.js +2 -2
  63. package/dist/components/ui/page-loader.js +1 -1
  64. package/dist/components/ui/product-card.d.ts.map +1 -1
  65. package/dist/components/ui/product-card.js +17 -17
  66. package/dist/components/ui/product-rating.js +1 -1
  67. package/dist/components/ui/product-stock-badge.js +2 -2
  68. package/dist/components/ui/review-form.js +2 -2
  69. package/dist/components/ui/route-skeleton-loader.js +6 -6
  70. package/dist/components/ui/sheet.d.ts +2 -1
  71. package/dist/components/ui/sheet.d.ts.map +1 -1
  72. package/dist/components/ui/sheet.js +4 -4
  73. package/dist/components/ui/skeleton.js +1 -1
  74. package/dist/components/ui/skeletons/index.js +5 -5
  75. package/dist/components/ui/skeletons/product-grid-skeleton.js +1 -1
  76. package/dist/components/ui/store-logos.d.ts.map +1 -1
  77. package/dist/components/ui/store-logos.js +4 -4
  78. package/dist/components/ui/toast.js +1 -1
  79. package/dist/components/ui/video-player.js +2 -2
  80. package/dist/editor/alignment-schemas/booking.js +1 -1
  81. package/dist/editor/alignment-schemas/clothing-minimal.js +1 -1
  82. package/dist/editor/alignment-schemas/index.js +20 -20
  83. package/dist/editor/alignment-schemas/lazy-loader.js +1 -1
  84. package/dist/editor/alignment-schemas/metadata.js +1 -1
  85. package/dist/editor/alignment-schemas/resolve-canvas-inspector-leaf.js +3 -3
  86. package/dist/editor/blocks/index.js +3 -3
  87. package/dist/editor/blocks/migrate-clothing-minimal.js +3 -3
  88. package/dist/editor/blocks/nav-outline-utils.js +2 -2
  89. package/dist/editor/blocks/registry.js +1 -1
  90. package/dist/editor/document/adapter.js +4 -4
  91. package/dist/editor/document/block-tree.js +1 -1
  92. package/dist/editor/document/index.js +6 -6
  93. package/dist/editor/document/validate.js +1 -1
  94. package/dist/editor/index.js +12 -12
  95. package/dist/editor/layout-content-loader.js +3 -3
  96. package/dist/editor/payaza-form/ArrayItemManager.js +2 -2
  97. package/dist/editor/payaza-form/EditorCanvasPreview.js +5 -5
  98. package/dist/editor/payaza-form/FieldRenderer.js +17 -17
  99. package/dist/editor/payaza-form/IframePreviewMessageBridge.js +3 -3
  100. package/dist/editor/payaza-form/PayazaFormEditor.js +31 -31
  101. package/dist/editor/payaza-form/PayazaFormEditorFullPage.js +2 -2
  102. package/dist/editor/payaza-form/SliderArrayEditor.js +3 -3
  103. package/dist/editor/payaza-form/components/ArrayField.js +1 -1
  104. package/dist/editor/payaza-form/components/BlockStylesInspector.js +1 -1
  105. package/dist/editor/payaza-form/components/BlocksField.js +9 -9
  106. package/dist/editor/payaza-form/components/ButtonField.js +3 -3
  107. package/dist/editor/payaza-form/components/CanvasGranularInspector.js +11 -11
  108. package/dist/editor/payaza-form/components/IconField.js +2 -2
  109. package/dist/editor/payaza-form/components/ImageField.js +1 -1
  110. package/dist/editor/payaza-form/components/NumberField.js +1 -1
  111. package/dist/editor/payaza-form/components/RichTextField.js +2 -2
  112. package/dist/editor/payaza-form/components/SectionField.js +1 -1
  113. package/dist/editor/payaza-form/components/SectionSchemaInspector.js +3 -3
  114. package/dist/editor/payaza-form/components/StarRatingField.js +2 -2
  115. package/dist/editor/payaza-form/components/TextField.js +1 -1
  116. package/dist/editor/payaza-form/data-merger.js +6 -6
  117. package/dist/editor/payaza-form/data-transformer.js +3 -3
  118. package/dist/editor/payaza-form/engine.js +1 -1
  119. package/dist/editor/payaza-form/examples/custom-widgets.example.js +1 -1
  120. package/dist/editor/payaza-form/index.js +8 -8
  121. package/dist/editor/payaza-form/layout-loader.js +2 -2
  122. package/dist/editor/payaza-form/preview-message-handler.js +3 -3
  123. package/dist/editor/payaza-form/schema-bridge.js +3 -3
  124. package/dist/editor/payaza-form/widget-registry.js +1 -1
  125. package/dist/editor/shared/BlockOutlineTree.js +2 -2
  126. package/dist/editor/shared/EditorHeader.js +2 -2
  127. package/dist/editor/shared/EditorNavigator.js +2 -2
  128. package/dist/editor/shared/IframePreview.js +6 -6
  129. package/dist/editor/shared/InlineCanvasPreview.js +8 -8
  130. package/dist/editor/shared/LayoutRenderer.js +1 -1
  131. package/dist/editor/shared/ResizableSidebar.js +1 -1
  132. package/dist/editor/shared/index.js +7 -7
  133. package/dist/hooks/use-analytics.js +3 -3
  134. package/dist/hooks/use-api.js +1 -1
  135. package/dist/hooks/use-cart-api.d.ts.map +1 -1
  136. package/dist/hooks/use-cart-api.js +8 -3
  137. package/dist/hooks/use-catalog-loader.js +3 -3
  138. package/dist/hooks/use-catalog-price-range.d.ts +2 -5
  139. package/dist/hooks/use-catalog-price-range.d.ts.map +1 -1
  140. package/dist/hooks/use-catalog-price-range.js +20 -5
  141. package/dist/hooks/use-category-products.d.ts +8 -0
  142. package/dist/hooks/use-category-products.d.ts.map +1 -0
  143. package/dist/hooks/use-category-products.js +43 -0
  144. package/dist/hooks/use-checkout-fees.d.ts +3 -4
  145. package/dist/hooks/use-checkout-fees.d.ts.map +1 -1
  146. package/dist/hooks/use-checkout-fees.js +1 -1
  147. package/dist/hooks/use-content-ready.js +1 -1
  148. package/dist/hooks/use-featured-products.d.ts +3 -0
  149. package/dist/hooks/use-featured-products.d.ts.map +1 -0
  150. package/dist/hooks/use-featured-products.js +25 -0
  151. package/dist/hooks/use-multi-store-checkout-fees.d.ts +3 -4
  152. package/dist/hooks/use-multi-store-checkout-fees.d.ts.map +1 -1
  153. package/dist/hooks/use-multi-store-checkout-fees.js +1 -1
  154. package/dist/hooks/use-navigation-loading.js +1 -1
  155. package/dist/hooks/use-payaza-checkout.d.ts +1 -1
  156. package/dist/hooks/use-payaza-checkout.d.ts.map +1 -1
  157. package/dist/hooks/use-payaza-checkout.js +9 -3
  158. package/dist/hooks/use-product-brands.d.ts +5 -0
  159. package/dist/hooks/use-product-brands.d.ts.map +1 -0
  160. package/dist/hooks/use-product-brands.js +25 -0
  161. package/dist/hooks/use-product-by-slug.d.ts +7 -0
  162. package/dist/hooks/use-product-by-slug.d.ts.map +1 -0
  163. package/dist/hooks/use-product-by-slug.js +38 -0
  164. package/dist/hooks/use-product-reviews.d.ts +15 -0
  165. package/dist/hooks/use-product-reviews.d.ts.map +1 -0
  166. package/dist/hooks/use-product-reviews.js +75 -0
  167. package/dist/hooks/use-product-variation-selection.d.ts +2 -8
  168. package/dist/hooks/use-product-variation-selection.d.ts.map +1 -1
  169. package/dist/hooks/use-product-variation-selection.js +1 -1
  170. package/dist/hooks/use-products-api.js +3 -3
  171. package/dist/hooks/use-shipping-quote.js +2 -2
  172. package/dist/hooks/use-store-api.js +4 -4
  173. package/dist/hooks/usePreviewSlideSync.js +1 -1
  174. package/dist/index.d.ts +62 -74
  175. package/dist/index.d.ts.map +1 -1
  176. package/dist/index.js +141 -153
  177. package/dist/layouts/booking/components/BookingHomePage.d.ts.map +1 -1
  178. package/dist/layouts/booking/components/BookingHomePage.js +68 -74
  179. package/dist/layouts/booking/components/BookingMultilineHeading.js +1 -1
  180. package/dist/layouts/booking/components/BookingTestimonialCard.js +2 -2
  181. package/dist/layouts/booking/components/BookingTestimonialsEmptyState.js +1 -1
  182. package/dist/layouts/booking/components/booking-footer-defaults.js +2 -2
  183. package/dist/layouts/booking/index.js +8 -8
  184. package/dist/layouts/booking/pages/AboutPage.d.ts +1 -1
  185. package/dist/layouts/booking/pages/AboutPage.d.ts.map +1 -1
  186. package/dist/layouts/booking/pages/AboutPage.js +39 -60
  187. package/dist/layouts/booking/pages/BookPage.d.ts.map +1 -1
  188. package/dist/layouts/booking/pages/BookPage.js +16 -22
  189. package/dist/layouts/booking/pages/CategoriesPage.js +6 -6
  190. package/dist/layouts/booking/pages/CategoryPage.d.ts +1 -1
  191. package/dist/layouts/booking/pages/CategoryPage.d.ts.map +1 -1
  192. package/dist/layouts/booking/pages/CategoryPage.js +17 -26
  193. package/dist/layouts/booking/pages/ContactPage.d.ts +1 -1
  194. package/dist/layouts/booking/pages/ContactPage.d.ts.map +1 -1
  195. package/dist/layouts/booking/pages/ContactPage.js +5 -12
  196. package/dist/layouts/booking/pages/ProductDetailPage.d.ts +1 -1
  197. package/dist/layouts/booking/pages/ProductDetailPage.d.ts.map +1 -1
  198. package/dist/layouts/booking/pages/ProductDetailPage.js +203 -150
  199. package/dist/layouts/booking/pages/ServicesPage.d.ts +1 -1
  200. package/dist/layouts/booking/pages/ServicesPage.d.ts.map +1 -1
  201. package/dist/layouts/booking/pages/ServicesPage.js +11 -31
  202. package/dist/layouts/booking-agenda/components/BookingHomePageAgenda.d.ts.map +1 -1
  203. package/dist/layouts/booking-agenda/components/BookingHomePageAgenda.js +21 -30
  204. package/dist/layouts/booking-agenda/index.js +8 -8
  205. package/dist/layouts/booking-agenda/pages/AboutPage.d.ts +1 -1
  206. package/dist/layouts/booking-agenda/pages/AboutPage.d.ts.map +1 -1
  207. package/dist/layouts/booking-agenda/pages/AboutPage.js +11 -14
  208. package/dist/layouts/booking-agenda/pages/BookPage.d.ts.map +1 -1
  209. package/dist/layouts/booking-agenda/pages/BookPage.js +15 -21
  210. package/dist/layouts/booking-agenda/pages/CategoriesPage.js +5 -5
  211. package/dist/layouts/booking-agenda/pages/CategoryPage.d.ts +1 -1
  212. package/dist/layouts/booking-agenda/pages/CategoryPage.d.ts.map +1 -1
  213. package/dist/layouts/booking-agenda/pages/CategoryPage.js +12 -18
  214. package/dist/layouts/booking-agenda/pages/ContactPage.d.ts +1 -1
  215. package/dist/layouts/booking-agenda/pages/ContactPage.d.ts.map +1 -1
  216. package/dist/layouts/booking-agenda/pages/ContactPage.js +8 -13
  217. package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts +1 -1
  218. package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts.map +1 -1
  219. package/dist/layouts/booking-agenda/pages/ProductDetailPage.js +202 -149
  220. package/dist/layouts/booking-agenda/pages/ServicesPage.d.ts +1 -1
  221. package/dist/layouts/booking-agenda/pages/ServicesPage.d.ts.map +1 -1
  222. package/dist/layouts/booking-agenda/pages/ServicesPage.js +8 -23
  223. package/dist/layouts/clothing/components/ClothingHomePage.d.ts.map +1 -1
  224. package/dist/layouts/clothing/components/ClothingHomePage.js +199 -136
  225. package/dist/layouts/clothing/index.js +7 -7
  226. package/dist/layouts/clothing/pages/AboutPage.d.ts +1 -1
  227. package/dist/layouts/clothing/pages/AboutPage.d.ts.map +1 -1
  228. package/dist/layouts/clothing/pages/AboutPage.js +19 -33
  229. package/dist/layouts/clothing/pages/CategoriesPage.js +8 -8
  230. package/dist/layouts/clothing/pages/CategoryPage.d.ts +1 -1
  231. package/dist/layouts/clothing/pages/CategoryPage.d.ts.map +1 -1
  232. package/dist/layouts/clothing/pages/CategoryPage.js +15 -41
  233. package/dist/layouts/clothing/pages/ContactPage.d.ts +1 -1
  234. package/dist/layouts/clothing/pages/ContactPage.d.ts.map +1 -1
  235. package/dist/layouts/clothing/pages/ContactPage.js +5 -8
  236. package/dist/layouts/clothing/pages/ProductDetailPage.d.ts +1 -1
  237. package/dist/layouts/clothing/pages/ProductDetailPage.d.ts.map +1 -1
  238. package/dist/layouts/clothing/pages/ProductDetailPage.js +256 -167
  239. package/dist/layouts/clothing/pages/ProductsPage.d.ts +1 -1
  240. package/dist/layouts/clothing/pages/ProductsPage.d.ts.map +1 -1
  241. package/dist/layouts/clothing/pages/ProductsPage.js +125 -59
  242. package/dist/layouts/clothing/payaza-bindings.js +2 -2
  243. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.d.ts.map +1 -1
  244. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.js +32 -131
  245. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.js +8 -8
  246. package/dist/layouts/clothing-minimal/index.js +7 -7
  247. package/dist/layouts/clothing-minimal/pages/AboutPage.d.ts +1 -1
  248. package/dist/layouts/clothing-minimal/pages/AboutPage.d.ts.map +1 -1
  249. package/dist/layouts/clothing-minimal/pages/AboutPage.js +37 -61
  250. package/dist/layouts/clothing-minimal/pages/CategoriesPage.js +7 -7
  251. package/dist/layouts/clothing-minimal/pages/CategoryPage.d.ts +1 -1
  252. package/dist/layouts/clothing-minimal/pages/CategoryPage.d.ts.map +1 -1
  253. package/dist/layouts/clothing-minimal/pages/CategoryPage.js +13 -18
  254. package/dist/layouts/clothing-minimal/pages/ContactPage.d.ts +1 -1
  255. package/dist/layouts/clothing-minimal/pages/ContactPage.d.ts.map +1 -1
  256. package/dist/layouts/clothing-minimal/pages/ContactPage.js +5 -8
  257. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts +1 -1
  258. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts.map +1 -1
  259. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.js +202 -143
  260. package/dist/layouts/clothing-minimal/pages/ProductsPage.d.ts +1 -1
  261. package/dist/layouts/clothing-minimal/pages/ProductsPage.d.ts.map +1 -1
  262. package/dist/layouts/clothing-minimal/pages/ProductsPage.js +126 -57
  263. package/dist/layouts/electronics/components/ElectronicsCategoriesPage.js +7 -7
  264. package/dist/layouts/electronics/components/ElectronicsGridProductCard.js +10 -10
  265. package/dist/layouts/electronics/components/ElectronicsHomePage.d.ts.map +1 -1
  266. package/dist/layouts/electronics/components/ElectronicsHomePage.js +29 -31
  267. package/dist/layouts/electronics/components/ElectronicsPageWrapper.js +4 -4
  268. package/dist/layouts/electronics/components/ElectronicsProductsPage.d.ts.map +1 -1
  269. package/dist/layouts/electronics/components/ElectronicsProductsPage.js +81 -23
  270. package/dist/layouts/electronics/components/ElectronicsStoreFooter.js +2 -2
  271. package/dist/layouts/electronics/components/ElectronicsStoreHeader.js +6 -6
  272. package/dist/layouts/electronics/index.js +18 -18
  273. package/dist/layouts/electronics/pages/AboutPage.d.ts +1 -1
  274. package/dist/layouts/electronics/pages/AboutPage.d.ts.map +1 -1
  275. package/dist/layouts/electronics/pages/AboutPage.js +11 -14
  276. package/dist/layouts/electronics/pages/CategoriesPage.js +1 -1
  277. package/dist/layouts/electronics/pages/CategoryPage.d.ts +1 -1
  278. package/dist/layouts/electronics/pages/CategoryPage.d.ts.map +1 -1
  279. package/dist/layouts/electronics/pages/CategoryPage.js +14 -20
  280. package/dist/layouts/electronics/pages/ContactPage.d.ts +1 -1
  281. package/dist/layouts/electronics/pages/ContactPage.d.ts.map +1 -1
  282. package/dist/layouts/electronics/pages/ContactPage.js +8 -13
  283. package/dist/layouts/electronics/pages/HelpCenterPage.js +1 -1
  284. package/dist/layouts/electronics/pages/PrivacyPolicyPage.js +1 -1
  285. package/dist/layouts/electronics/pages/ProductDetailPage.d.ts +1 -1
  286. package/dist/layouts/electronics/pages/ProductDetailPage.d.ts.map +1 -1
  287. package/dist/layouts/electronics/pages/ProductDetailPage.js +201 -142
  288. package/dist/layouts/electronics/pages/ProductsPage.d.ts +1 -1
  289. package/dist/layouts/electronics/pages/ProductsPage.d.ts.map +1 -1
  290. package/dist/layouts/electronics/pages/ProductsPage.js +119 -49
  291. package/dist/layouts/electronics/pages/TermsPage.js +1 -1
  292. package/dist/layouts/electronics/pages/TrackOrderPage.js +4 -4
  293. package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.js +10 -10
  294. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.d.ts.map +1 -1
  295. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.js +75 -33
  296. package/dist/layouts/electronics-grid/index.js +14 -14
  297. package/dist/layouts/electronics-grid/pages/AboutPage.d.ts +1 -1
  298. package/dist/layouts/electronics-grid/pages/AboutPage.d.ts.map +1 -1
  299. package/dist/layouts/electronics-grid/pages/AboutPage.js +11 -14
  300. package/dist/layouts/electronics-grid/pages/CategoriesPage.js +1 -1
  301. package/dist/layouts/electronics-grid/pages/CategoryPage.d.ts +1 -1
  302. package/dist/layouts/electronics-grid/pages/CategoryPage.d.ts.map +1 -1
  303. package/dist/layouts/electronics-grid/pages/CategoryPage.js +14 -20
  304. package/dist/layouts/electronics-grid/pages/ContactPage.d.ts +1 -1
  305. package/dist/layouts/electronics-grid/pages/ContactPage.d.ts.map +1 -1
  306. package/dist/layouts/electronics-grid/pages/ContactPage.js +8 -13
  307. package/dist/layouts/electronics-grid/pages/ElectronicsGridCategoriesPage.js +6 -6
  308. package/dist/layouts/electronics-grid/pages/HelpCenterPage.js +1 -1
  309. package/dist/layouts/electronics-grid/pages/PrivacyPolicyPage.js +1 -1
  310. package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts +1 -1
  311. package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts.map +1 -1
  312. package/dist/layouts/electronics-grid/pages/ProductDetailPage.js +201 -142
  313. package/dist/layouts/electronics-grid/pages/ProductsPage.d.ts +1 -1
  314. package/dist/layouts/electronics-grid/pages/ProductsPage.d.ts.map +1 -1
  315. package/dist/layouts/electronics-grid/pages/ProductsPage.js +121 -52
  316. package/dist/layouts/electronics-grid/pages/TermsPage.js +1 -1
  317. package/dist/layouts/electronics-grid/pages/TrackOrderPage.js +4 -4
  318. package/dist/layouts/food/components/FoodHomePage.d.ts.map +1 -1
  319. package/dist/layouts/food/components/FoodHomePage.js +42 -41
  320. package/dist/layouts/food/index.js +8 -8
  321. package/dist/layouts/food/pages/AboutPage.d.ts +1 -1
  322. package/dist/layouts/food/pages/AboutPage.d.ts.map +1 -1
  323. package/dist/layouts/food/pages/AboutPage.js +44 -45
  324. package/dist/layouts/food/pages/CategoriesPage.js +6 -6
  325. package/dist/layouts/food/pages/CategoryPage.d.ts +1 -1
  326. package/dist/layouts/food/pages/CategoryPage.d.ts.map +1 -1
  327. package/dist/layouts/food/pages/CategoryPage.js +23 -21
  328. package/dist/layouts/food/pages/ContactPage.d.ts +1 -1
  329. package/dist/layouts/food/pages/ContactPage.d.ts.map +1 -1
  330. package/dist/layouts/food/pages/ContactPage.js +5 -7
  331. package/dist/layouts/food/pages/MenuPage.d.ts +1 -1
  332. package/dist/layouts/food/pages/MenuPage.d.ts.map +1 -1
  333. package/dist/layouts/food/pages/MenuPage.js +81 -42
  334. package/dist/layouts/food/pages/ProductDetailPage.d.ts +1 -1
  335. package/dist/layouts/food/pages/ProductDetailPage.d.ts.map +1 -1
  336. package/dist/layouts/food/pages/ProductDetailPage.js +209 -171
  337. package/dist/layouts/food/pages/ProductsPage.d.ts +1 -1
  338. package/dist/layouts/food/pages/ProductsPage.d.ts.map +1 -1
  339. package/dist/layouts/food/pages/ProductsPage.js +130 -45
  340. package/dist/layouts/food-modern/components/FoodHomePageModern.js +10 -10
  341. package/dist/layouts/food-modern/index.js +8 -8
  342. package/dist/layouts/food-modern/pages/AboutPage.d.ts +1 -1
  343. package/dist/layouts/food-modern/pages/AboutPage.d.ts.map +1 -1
  344. package/dist/layouts/food-modern/pages/AboutPage.js +11 -14
  345. package/dist/layouts/food-modern/pages/CategoriesPage.js +5 -5
  346. package/dist/layouts/food-modern/pages/CategoryPage.d.ts +1 -1
  347. package/dist/layouts/food-modern/pages/CategoryPage.d.ts.map +1 -1
  348. package/dist/layouts/food-modern/pages/CategoryPage.js +23 -20
  349. package/dist/layouts/food-modern/pages/ContactPage.d.ts +1 -1
  350. package/dist/layouts/food-modern/pages/ContactPage.d.ts.map +1 -1
  351. package/dist/layouts/food-modern/pages/ContactPage.js +5 -7
  352. package/dist/layouts/food-modern/pages/MenuPage.d.ts +1 -1
  353. package/dist/layouts/food-modern/pages/MenuPage.d.ts.map +1 -1
  354. package/dist/layouts/food-modern/pages/MenuPage.js +81 -46
  355. package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts +1 -1
  356. package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts.map +1 -1
  357. package/dist/layouts/food-modern/pages/ProductDetailPage.js +202 -143
  358. package/dist/layouts/food-modern/pages/ProductsPage.d.ts +1 -1
  359. package/dist/layouts/food-modern/pages/ProductsPage.d.ts.map +1 -1
  360. package/dist/layouts/food-modern/pages/ProductsPage.js +117 -33
  361. package/dist/layouts/motivational-speaker/components/MotivationalHomePage.d.ts.map +1 -1
  362. package/dist/layouts/motivational-speaker/components/MotivationalHomePage.js +32 -23
  363. package/dist/layouts/motivational-speaker/components/MotivationalSpeakerPageWrapper.js +1 -1
  364. package/dist/layouts/motivational-speaker/index.js +9 -9
  365. package/dist/layouts/motivational-speaker/pages/AboutPage.d.ts +1 -1
  366. package/dist/layouts/motivational-speaker/pages/AboutPage.d.ts.map +1 -1
  367. package/dist/layouts/motivational-speaker/pages/AboutPage.js +6 -9
  368. package/dist/layouts/motivational-speaker/pages/CategoryPage.d.ts +1 -1
  369. package/dist/layouts/motivational-speaker/pages/CategoryPage.d.ts.map +1 -1
  370. package/dist/layouts/motivational-speaker/pages/CategoryPage.js +18 -22
  371. package/dist/layouts/motivational-speaker/pages/ContactPage.d.ts +1 -1
  372. package/dist/layouts/motivational-speaker/pages/ContactPage.d.ts.map +1 -1
  373. package/dist/layouts/motivational-speaker/pages/ContactPage.js +9 -13
  374. package/dist/layouts/motivational-speaker/pages/ProductsPage.d.ts +1 -1
  375. package/dist/layouts/motivational-speaker/pages/ProductsPage.d.ts.map +1 -1
  376. package/dist/layouts/motivational-speaker/pages/ProductsPage.js +121 -52
  377. package/dist/layouts/motivational-speaker/pages/ServiceDetailPage.d.ts +1 -1
  378. package/dist/layouts/motivational-speaker/pages/ServiceDetailPage.d.ts.map +1 -1
  379. package/dist/layouts/motivational-speaker/pages/ServiceDetailPage.js +15 -24
  380. package/dist/layouts/motivational-speaker/pages/ServicesPage.d.ts +1 -1
  381. package/dist/layouts/motivational-speaker/pages/ServicesPage.d.ts.map +1 -1
  382. package/dist/layouts/motivational-speaker/pages/ServicesPage.js +8 -23
  383. package/dist/layouts/motivational-speaker/pages/SubscriptionPage.js +7 -7
  384. package/dist/layouts/shared/components/BaseStoreLayout.js +9 -9
  385. package/dist/layouts/shared/components/CartLineQuantityControl.js +1 -1
  386. package/dist/layouts/shared/components/GenericPageWrapper.js +3 -3
  387. package/dist/layouts/shared/components/ProductPriceFilterSection.js +4 -4
  388. package/dist/layouts/shared/components/PromoBanner.d.ts +1 -4
  389. package/dist/layouts/shared/components/PromoBanner.d.ts.map +1 -1
  390. package/dist/layouts/shared/components/PromoBanner.js +12 -8
  391. package/dist/layouts/shared/components/StoreFooter.js +10 -10
  392. package/dist/layouts/shared/components/StoreHeader.js +7 -7
  393. package/dist/layouts/shared/components/TestimonialCard.d.ts.map +1 -1
  394. package/dist/layouts/shared/components/TestimonialCard.js +2 -2
  395. package/dist/layouts/shared/components/headers/BookingAgendaSidebar.js +2 -2
  396. package/dist/layouts/shared/components/headers/ClothingMinimalHeader.js +11 -11
  397. package/dist/layouts/shared/components/headers/FoodModernHeader.js +7 -7
  398. package/dist/layouts/shared/index.js +22 -22
  399. package/dist/layouts/shared/pages/AccountPage.d.ts.map +1 -1
  400. package/dist/layouts/shared/pages/AccountPage.js +101 -27
  401. package/dist/layouts/shared/pages/CartPage.d.ts.map +1 -1
  402. package/dist/layouts/shared/pages/CartPage.js +39 -90
  403. package/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
  404. package/dist/layouts/shared/pages/CheckoutPage.js +349 -868
  405. package/dist/layouts/shared/pages/CookiePolicyPage.js +1 -1
  406. package/dist/layouts/shared/pages/FeatureDisabledPage.js +1 -1
  407. package/dist/layouts/shared/pages/HelpCenterPage.js +1 -1
  408. package/dist/layouts/shared/pages/MaintenancePage.d.ts.map +1 -1
  409. package/dist/layouts/shared/pages/MaintenancePage.js +2 -3
  410. package/dist/layouts/shared/pages/PortfolioPage.d.ts.map +1 -1
  411. package/dist/layouts/shared/pages/PortfolioPage.js +2 -2
  412. package/dist/layouts/shared/pages/PrivacyPolicyPage.js +1 -1
  413. package/dist/layouts/shared/pages/SizeGuidePage.js +1 -1
  414. package/dist/layouts/shared/pages/StyleGuidePage.js +3 -3
  415. package/dist/layouts/shared/pages/TeamPage.d.ts.map +1 -1
  416. package/dist/layouts/shared/pages/TeamPage.js +1 -1
  417. package/dist/layouts/shared/pages/TermsPage.js +1 -1
  418. package/dist/layouts/shared/pages/TrackOrderPage.js +4 -4
  419. package/dist/layouts/shared/pages/WishlistPage.d.ts.map +1 -1
  420. package/dist/layouts/shared/pages/WishlistPage.js +44 -29
  421. package/dist/layouts/shared/wrappers/BookingAgendaLayout.d.ts.map +1 -1
  422. package/dist/layouts/shared/wrappers/BookingAgendaLayout.js +80 -35
  423. package/dist/layouts/shared/wrappers/ClothingLayout.js +8 -8
  424. package/dist/layouts/shared/wrappers/ClothingMinimalLayout.js +7 -7
  425. package/dist/layouts/shared/wrappers/ElectronicsLayout.js +5 -5
  426. package/dist/layouts/shared/wrappers/FoodModernLayout.js +6 -6
  427. package/dist/layouts/shared/wrappers/MotivationalLayout.js +9 -9
  428. package/dist/layouts/shared/wrappers/StandardLayout.js +8 -8
  429. package/dist/lib/api.d.ts +3 -4
  430. package/dist/lib/api.d.ts.map +1 -1
  431. package/dist/lib/api.js +69 -109
  432. package/dist/lib/auth-context.js +2 -2
  433. package/dist/lib/content-selectors.d.ts +1 -1
  434. package/dist/lib/content-selectors.d.ts.map +1 -1
  435. package/dist/lib/content-selectors.js +8 -0
  436. package/dist/lib/layout-config-hydration.js +2 -2
  437. package/dist/lib/loading-context.d.ts.map +1 -1
  438. package/dist/lib/loading-context.js +11 -21
  439. package/dist/lib/payaza-checkout.d.ts.map +1 -1
  440. package/dist/lib/payaza-checkout.js +2 -4
  441. package/dist/lib/payaza-public-key.d.ts +6 -0
  442. package/dist/lib/payaza-public-key.d.ts.map +1 -0
  443. package/dist/lib/payaza-public-key.js +10 -0
  444. package/dist/lib/rich-html.d.ts +31 -26
  445. package/dist/lib/rich-html.d.ts.map +1 -1
  446. package/dist/lib/rich-html.js +1 -0
  447. package/dist/lib/services/analytics.service.js +1 -1
  448. package/dist/lib/services/auth.service.js +1 -1
  449. package/dist/lib/services/booking.service.js +1 -1
  450. package/dist/lib/services/category.service.js +1 -1
  451. package/dist/lib/services/checkout.service.d.ts +3 -0
  452. package/dist/lib/services/checkout.service.d.ts.map +1 -1
  453. package/dist/lib/services/checkout.service.js +1 -1
  454. package/dist/lib/services/contact.service.js +1 -1
  455. package/dist/lib/services/customer.service.js +1 -1
  456. package/dist/lib/services/fees.service.d.ts +17 -63
  457. package/dist/lib/services/fees.service.d.ts.map +1 -1
  458. package/dist/lib/services/fees.service.js +4 -138
  459. package/dist/lib/services/index.js +13 -13
  460. package/dist/lib/services/location.service.js +1 -1
  461. package/dist/lib/services/order.service.js +1 -1
  462. package/dist/lib/services/payment.service.js +1 -1
  463. package/dist/lib/services/product.service.d.ts +7 -2
  464. package/dist/lib/services/product.service.d.ts.map +1 -1
  465. package/dist/lib/services/product.service.js +13 -1
  466. package/dist/lib/services/promo.service.js +1 -1
  467. package/dist/lib/services/review.service.js +1 -1
  468. package/dist/lib/services/service.service.js +1 -1
  469. package/dist/lib/services/shipping.service.js +1 -1
  470. package/dist/lib/services/store.service.js +1 -1
  471. package/dist/lib/store-config-utils.d.ts +1 -10
  472. package/dist/lib/store-config-utils.d.ts.map +1 -1
  473. package/dist/lib/store-config-utils.js +73 -261
  474. package/dist/lib/store-config.js +1 -1
  475. package/dist/lib/store-context.d.ts +1 -23
  476. package/dist/lib/store-context.d.ts.map +1 -1
  477. package/dist/lib/store-context.js +89 -111
  478. package/dist/lib/store-types.d.ts +9 -91
  479. package/dist/lib/store-types.d.ts.map +1 -1
  480. package/dist/lib/utils/asset-helpers.js +1 -1
  481. package/dist/lib/utils/catalog-price-bounds.d.ts +16 -6
  482. package/dist/lib/utils/catalog-price-bounds.d.ts.map +1 -1
  483. package/dist/lib/utils/catalog-price-bounds.js +58 -14
  484. package/dist/lib/utils/category-tree.d.ts +9 -0
  485. package/dist/lib/utils/category-tree.d.ts.map +1 -1
  486. package/dist/lib/utils/category-tree.js +26 -0
  487. package/dist/lib/utils/editor-preview.d.ts +5 -0
  488. package/dist/lib/utils/editor-preview.d.ts.map +1 -1
  489. package/dist/lib/utils/editor-preview.js +17 -3
  490. package/dist/lib/utils/fee-calculations.d.ts +5 -1
  491. package/dist/lib/utils/fee-calculations.d.ts.map +1 -1
  492. package/dist/lib/utils/fee-calculations.js +28 -31
  493. package/dist/lib/utils/index.d.ts +1 -1
  494. package/dist/lib/utils/index.d.ts.map +1 -1
  495. package/dist/lib/utils/index.js +4 -4
  496. package/dist/lib/utils/product-images.js +1 -1
  497. package/dist/lib/utils/product-share.js +1 -1
  498. package/dist/lib/utils/url-helpers.d.ts +6 -0
  499. package/dist/lib/utils/url-helpers.d.ts.map +1 -1
  500. package/dist/lib/utils/url-helpers.js +20 -4
  501. package/dist/preview/LayoutPreview.js +6 -6
  502. package/dist/preview/PreviewRouter.js +4 -4
  503. package/dist/preview/canvas/PreviewCanvasEnhancer.js +8 -8
  504. package/dist/preview/canvas/preview-flush-await.js +1 -1
  505. package/dist/preview/canvas/preview-isolation.js +1 -1
  506. package/dist/preview/canvas/preview-route.js +2 -2
  507. package/dist/preview/index.js +5 -5
  508. package/dist/styles/index.css +190 -149
  509. package/package.json +31 -43
@@ -1,42 +1,31 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { shareProductLink } from '../../../lib/utils/product-share.js';
4
- import { Button } from '../../../components/ui/button.js';
5
- import { Breadcrumbs } from '../../../components/ui/breadcrumbs.js';
6
- import { Modal } from '../../../components/ui/modal.js';
7
- import { ShoppingCart, Heart, Star, Truck, CheckCircle, ThumbsUp, User, Minus, Plus, Share2, ChevronDown, MapPin } from 'lucide-react';
3
+ import { useProductBySlug } from '../../../hooks/use-product-by-slug';
4
+ import { useProductReviews } from '../../../hooks/use-product-reviews';
5
+ import { Button } from '../../../components/ui/button';
6
+ import { Breadcrumbs } from '../../../components/ui/breadcrumbs';
7
+ import { Modal } from '../../../components/ui/modal';
8
+ import { ShoppingCart, Heart, Star, CheckCircle, ThumbsUp, User, Minus, Plus, Ruler, Share2, Info } from 'lucide-react';
8
9
  import { useState, useMemo, useEffect } from 'react';
9
- import { useStore } from '../../../lib/store-context.js';
10
- import { useToast } from '../../../components/ui/toast.js';
10
+ import { useStore } from '../../../lib/store-context';
11
+ import { useToast } from '../../../components/ui/toast';
11
12
  import { useRouter } from 'next/navigation';
12
- import { useAuth } from '../../../lib/auth-context.js';
13
- import { useAnalytics } from '../../../hooks/use-analytics.js';
14
- import { trackStorefrontEvent } from '../../../lib/mixpanel.js';
15
- import { customerService } from '../../../lib/services/customer.service.js';
16
- import { GuestCheckoutModal } from '../../../components/ui/guest-checkout-modal.js';
17
- import { getGuestUserInfo, saveGuestUserInfo } from '../../../lib/guest-user.js';
18
- import { ProductCard } from '../../../components/ui/product-card.js';
13
+ import { useAuth } from '../../../lib/auth-context';
14
+ import { useAnalytics } from '../../../hooks/use-analytics';
15
+ import { customerService } from '../../../lib/services/customer.service';
16
+ import { GuestCheckoutModal } from '../../../components/ui/guest-checkout-modal';
17
+ import { getGuestUserInfo, saveGuestUserInfo } from '../../../lib/guest-user';
18
+ import { ProductCard } from '../../../components/ui/product-card';
19
19
  import Image from 'next/image';
20
- import { ImageWithFallback } from '../../../components/ui/image-with-fallback.js';
21
- import { ButtonLoader } from '../../../components/ui/page-loader.js';
22
- import { extractImageUrls } from '../../../lib/store-config-utils.js';
23
- import { OutOfStockOverlay } from '../../../components/ui/out-of-stock-overlay.js';
24
- import { ProductStockBadge } from '../../../components/ui/product-stock-badge.js';
25
- import { LimitedTimeOfferBadge } from '../../../components/ui/limited-time-offer-badge.js';
26
- import { getProductStockInfo, getMaxPurchasableQuantity, formatStockLimitMessage } from '../../../lib/inventory-utils.js';
27
- import { cn, formatCurrency, isEditorPreviewMode, resolveProductBySlugForDisplay, resolveStoreProductsForDisplay, } from '../../../lib/utils/index.js';
28
- import { useShippingQuote } from '../../../hooks/use-shipping-quote.js';
29
- import { ShippingQuoteAddressForm } from '../../../components/shipping/ShippingQuoteAddressForm.js';
30
- import { MerchantHandledDeliveryNotice } from '../../../components/shipping/MerchantHandledDeliveryNotice.js';
31
- import { isAutomatedShippingEnabled } from '../../../lib/shipping-settings.util.js';
32
- import { enrichShippingQuoteAddress } from '../../../lib/shipping-address.util.js';
33
- import { guardCheckoutAvailable, isCheckoutDisabled } from '../../../lib/checkout-availability.js';
34
- import { locationService } from '../../../lib/services/location.service.js';
35
- import { useProductVariationSelection } from '../../../hooks/use-product-variation-selection.js';
36
- import { ProductVariationSelectors } from '../../../components/product/ProductVariationSelectors.js';
37
- import { findMatchingVariation, resolveVariantPrice, resolveVariantSKU, resolveVariantStockProduct, resolveVariantImageUrls, buildCartLineProduct, } from '../../../lib/product-variation-utils.js';
38
- import { formatDateSafe } from '../../../utils/date.js';
39
- import { payazaInlineBindingProps } from '../../../preview/canvas/field-key.js';
20
+ import { ImageWithFallback } from '../../../components/ui/image-with-fallback';
21
+ import { ButtonLoader } from '../../../components/ui/page-loader';
22
+ import { extractImageUrls } from '../../../lib/store-config-utils';
23
+ import { OutOfStockOverlay } from '../../../components/ui/out-of-stock-overlay';
24
+ import { cn, formatCurrency, filterActiveProducts, isEditorPreviewMode, resolvePdpProduct } from '../../../lib/utils';
25
+ import { shippingService } from '../../../lib/services/shipping.service';
26
+ import { locationService } from '../../../lib/services/location.service';
27
+ import { ProductDeliveryInfoSection } from '../../../components/shipping/ProductDeliveryInfoSection';
28
+ import { formatDateSafe } from '../../../utils/date';
40
29
  // Helper function to format date
41
30
  const formatDate = (dateString) => {
42
31
  return formatDateSafe(dateString, '—', { year: 'numeric', month: 'long', day: 'numeric' });
@@ -58,44 +47,50 @@ function StarRating({ rating, size = 'md', className = '' }) {
58
47
  return (_jsxs("div", { className: `relative inline-block ${sizeClasses[size]}`, children: [_jsx(Star, { className: `w-full h-full absolute inset-0 text-gray-200 fill-gray-200` }), isHalf && (_jsx("div", { className: "absolute inset-0", style: { clipPath: 'inset(0 50% 0 0)' }, children: _jsx(Star, { className: `w-full h-full text-gray-900 fill-gray-900` }) })), isFull && (_jsx(Star, { className: `w-full h-full absolute inset-0 text-gray-900 fill-gray-900` }))] }, i));
59
48
  }) }));
60
49
  }
61
- import { ProductDescription } from '../../../components/rich-text/ProductDescription.js';
62
50
  function ReviewCard({ review }) {
63
- return (_jsxs("div", { className: "border-b border-gray-100 pb-8 last:border-b-0 last:pb-0", children: [_jsx("div", { className: "flex items-start justify-between mb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "w-12 h-12 rounded-full bg-gradient-to-br from-gray-200 to-gray-300 flex items-center justify-center flex-shrink-0 ring-2 ring-white shadow-sm overflow-hidden", children: [review.userAvatar ? (_jsx(Image, { src: review.userAvatar, alt: review.userName, fill: true, className: "w-full h-full object-cover", unoptimized: true })) : null, _jsx(User, { className: "h-6 w-6 text-gray-600", style: { display: review.userAvatar ? 'none' : 'flex' } })] }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("span", { className: "font-semibold text-gray-900", children: review.userName }), review.verified && (_jsx("span", { className: "text-xs bg-blue-50 text-blue-700 px-2.5 py-1 rounded-full font-medium border border-blue-100", children: "Verified Purchase" }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StarRating, { rating: review.rating, size: "sm" }), _jsx("span", { className: "text-xs text-gray-500", children: formatDate(review.date) })] })] })] }) }), review.title && (_jsx("h4", { className: "font-semibold text-gray-900 mb-3 text-lg", children: review.title })), _jsx("p", { className: "text-gray-700 leading-relaxed mb-4", children: review.comment }), review.images && review.images.length > 0 && (_jsx("div", { className: "flex gap-2 mb-4", children: review.images.map((img, idx) => (_jsx("div", { className: "relative w-20 h-20 rounded-lg overflow-hidden border border-gray-200", children: _jsx(Image, { src: img, alt: `${review.userName}'s review image ${idx + 1}`, fill: true, className: "object-cover", unoptimized: true }) }, idx))) })), review.helpful !== undefined && (_jsx("div", { className: "flex items-center gap-4", children: _jsxs("button", { className: "flex items-center gap-1.5 text-xs text-gray-600 hover:text-gray-900 transition-colors font-medium", children: [_jsx(ThumbsUp, { className: "h-4 w-4" }), _jsxs("span", { children: ["Helpful (", review.helpful, ")"] })] }) }))] }));
51
+ return (_jsxs("div", { className: "border-b border-gray-100 pb-8 last:border-b-0 last:pb-0", children: [_jsx("div", { className: "flex items-start justify-between mb-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "w-12 h-12 rounded-full bg-gradient-to-br from-gray-200 to-gray-300 flex items-center justify-center flex-shrink-0 ring-2 ring-white shadow-sm overflow-hidden", children: [review.userAvatar ? (_jsx(Image, { src: review.userAvatar, alt: review.userName, fill: true, className: "w-full h-full object-cover" })) : null, _jsx(User, { className: "h-6 w-6 text-gray-600", style: { display: review.userAvatar ? 'none' : 'flex' } })] }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2 mb-1", children: [_jsx("span", { className: "font-semibold text-gray-900", children: review.userName }), review.verified && (_jsx("span", { className: "text-xs bg-blue-50 text-blue-700 px-2.5 py-1 rounded-full font-medium border border-blue-100", children: "Verified Purchase" }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StarRating, { rating: review.rating, size: "sm" }), _jsx("span", { className: "text-xs text-gray-500", children: formatDate(review.date) })] })] })] }) }), review.title && (_jsx("h4", { className: "font-semibold text-gray-900 mb-3 text-lg", children: review.title })), _jsx("p", { className: "text-gray-700 leading-relaxed mb-4", children: review.comment }), review.images && review.images.length > 0 && (_jsx("div", { className: "flex gap-2 mb-4", children: review.images.map((img, idx) => (_jsx("div", { className: "relative w-20 h-20 rounded-lg overflow-hidden border border-gray-200", children: _jsx(Image, { src: img, alt: `${review.userName}'s review image ${idx + 1}`, fill: true, className: "object-cover" }) }, idx))) })), review.helpful !== undefined && (_jsx("div", { className: "flex items-center gap-4", children: _jsxs("button", { className: "flex items-center gap-1.5 text-xs text-gray-600 hover:text-gray-900 transition-colors font-medium", children: [_jsx(ThumbsUp, { className: "h-4 w-4" }), _jsxs("span", { children: ["Helpful (", review.helpful, ")"] })] }) }))] }));
64
52
  }
65
- export function FoodProductDetailPage({ storeConfig, productSlug }) {
66
- const menuItemConfig = storeConfig.layoutConfig?.pages?.productDetail?.menuItemInfo;
67
- const isPreview = isEditorPreviewMode(storeConfig);
68
- const products = resolveStoreProductsForDisplay(storeConfig.products, isPreview);
69
- const product = resolveProductBySlugForDisplay(storeConfig.products, productSlug, isPreview);
70
- const { optionGroups, selectedAttributes, setAttribute, selectedColor, selectedSize, matchingVariation, hasVariations, hasSelectedOptions, } = useProductVariationSelection(product?.variants);
53
+ export function ProductDetailPage({ storeConfig, productSlug }) {
54
+ const products = filterActiveProducts(storeConfig.products || []);
55
+ const initialProduct = resolvePdpProduct(initialConfig.products, storeConfig.products, productSlug, isEditorPreviewMode(storeConfig));
56
+ const { product, relatedProducts: apiRelatedProducts, isLoading: isLoadingProduct } = useProductBySlug(storeConfig.id, productSlug, initialProduct);
71
57
  const { addToCart, isCartLoading, toggleWishlist, isInWishlist, isWishlistLoading, setBuyNowItem } = useStore();
72
58
  const { addToast } = useToast();
73
59
  const router = useRouter();
74
- const { isAuthenticated } = useAuth();
60
+ const { isAuthenticated, openLogin } = useAuth();
75
61
  const { trackEvent } = useAnalytics();
62
+ const { reviews, isSubmitting: isSubmittingReview, submitReview, } = useProductReviews(product?.id);
76
63
  // Related products logic
77
- const relatedProducts = useMemo(() => {
64
+ const fallbackRelatedProducts = useMemo(() => {
78
65
  if (!product)
79
66
  return [];
80
67
  return products
81
68
  .filter(p => p.categoryId === product.categoryId && p.id !== product.id)
82
69
  .slice(0, 4);
83
70
  }, [product, products]);
71
+ const relatedProducts = apiRelatedProducts.length > 0 ? apiRelatedProducts : fallbackRelatedProducts;
84
72
  const handleShare = async () => {
85
- if (!product)
86
- return;
87
- try {
88
- const result = await shareProductLink({
89
- storeSlug: storeConfig.slug,
90
- productSlug: product.slug,
91
- productName: product.name,
92
- });
93
- addToast(result === 'shared' ? 'Product shared!' : 'Link copied to clipboard!', 'success');
73
+ if (typeof navigator !== 'undefined' && navigator.share) {
74
+ try {
75
+ await navigator.share({
76
+ title: product?.name,
77
+ text: product?.description,
78
+ url: window.location.href,
79
+ });
80
+ }
81
+ catch (error) {
82
+ console.log('Error sharing:', error);
83
+ }
94
84
  }
95
- catch (error) {
96
- if (error instanceof Error && error.name === 'AbortError')
97
- return;
98
- addToast('Failed to copy link', 'error');
85
+ else {
86
+ // Fallback to copy to clipboard
87
+ try {
88
+ await navigator.clipboard.writeText(window.location.href);
89
+ addToast('Link copied to clipboard!', 'success');
90
+ }
91
+ catch (err) {
92
+ addToast('Failed to copy link', 'error');
93
+ }
99
94
  }
100
95
  };
101
96
  const handleQuickView = (p) => {
@@ -120,6 +115,9 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
120
115
  addToast('Failed to update wishlist', 'error');
121
116
  }
122
117
  };
118
+ // Extract color and size variants
119
+ const colorVariants = product?.variants?.filter(v => v.name === 'Color') || [];
120
+ const sizeVariants = product?.variants?.filter(v => v.name === 'Size') || [];
123
121
  // Initialize state with defaults
124
122
  const [selectedImage, setSelectedImage] = useState(0);
125
123
  // Ensure selectedImage is within bounds when images change
@@ -130,7 +128,9 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
130
128
  return () => clearTimeout(timer);
131
129
  }
132
130
  }, [product, selectedImage]);
133
- const [quantity, setQuantity] = useState(1);
131
+ const [selectedColor, setSelectedColor] = useState('');
132
+ const [selectedSize, setSelectedSize] = useState('');
133
+ // Pickup/Delivery state
134
134
  const [isPickup, setIsPickup] = useState(true); // Default to pickup
135
135
  const [locations, setLocations] = useState([]);
136
136
  const [selectedLocation, setSelectedLocation] = useState(null);
@@ -164,36 +164,66 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
164
164
  return () => clearTimeout(timer);
165
165
  }
166
166
  }, [product, selectedImage]);
167
- // Pickup/Delivery state
167
+ const [quantity, setQuantity] = useState(1);
168
168
  const [showAllReviews, setShowAllReviews] = useState(false);
169
169
  const [isReviewModalOpen, setIsReviewModalOpen] = useState(false);
170
170
  const [newReview, setNewReview] = useState({ rating: 5, title: '', comment: '' });
171
171
  const [showGuestModal, setShowGuestModal] = useState(false);
172
172
  const [isBuyNowLoading, setIsBuyNowLoading] = useState(false);
173
- // Shipping calculation (ShipBubble-ready address fields)
174
- const currency = product?.currency || storeConfig.settings?.currency || 'USD';
175
- const { address: shippingAddress, updateAddress: updateShippingAddress, methods: shippingMethods, isCalculating: isCalculatingShipping, error: shippingError, freeShippingEligible, freeShippingThreshold, } = useShippingQuote({
176
- storeId: storeConfig.id,
177
- productId: product?.id || '',
178
- productPrice: resolveVariantPrice({ price: product?.price ?? 0 }, matchingVariation),
179
- currency,
180
- quantity,
181
- enabled: Boolean(product) && isAutomatedShippingEnabled(storeConfig),
173
+ // Shipping calculation state
174
+ const [shippingAddress, setShippingAddress] = useState({
175
+ country: '',
176
+ city: '',
177
+ zipCode: '',
182
178
  });
183
179
  const [savedAddresses, setSavedAddresses] = useState([]);
184
- const handleSubmitReview = (e) => {
180
+ const [isCountryDropdownOpen, setIsCountryDropdownOpen] = useState(false);
181
+ const [isCityDropdownOpen, setIsCityDropdownOpen] = useState(false);
182
+ const [shippingMethods, setShippingMethods] = useState([]);
183
+ const [isCalculatingShipping, setIsCalculatingShipping] = useState(false);
184
+ const [shippingError, setShippingError] = useState(null);
185
+ const [freeShippingEligible, setFreeShippingEligible] = useState(false);
186
+ const [freeShippingThreshold, setFreeShippingThreshold] = useState(undefined);
187
+ const handleSubmitReview = async (e) => {
185
188
  e.preventDefault();
186
- // In a real app, this would submit to API
187
- addToast('Review submitted successfully!', 'success');
188
- setIsReviewModalOpen(false);
189
- setNewReview({ rating: 5, title: '', comment: '' });
189
+ if (!product?.id)
190
+ return;
191
+ if (!isAuthenticated) {
192
+ setIsReviewModalOpen(false);
193
+ openLogin({
194
+ onSuccess: () => setIsReviewModalOpen(true),
195
+ });
196
+ addToast('Sign in to submit your review', 'info');
197
+ return;
198
+ }
199
+ const title = newReview.title.trim();
200
+ const comment = newReview.comment.trim();
201
+ if (!title && !comment) {
202
+ addToast('Please add a review title or comment', 'error');
203
+ return;
204
+ }
205
+ try {
206
+ await submitReview({
207
+ rating: newReview.rating,
208
+ title,
209
+ comment,
210
+ });
211
+ addToast('Review submitted successfully!', 'success');
212
+ setIsReviewModalOpen(false);
213
+ setNewReview({ rating: 5, title: '', comment: '' });
214
+ }
215
+ catch (error) {
216
+ addToast(error instanceof Error ? error.message : 'Failed to submit review', 'error');
217
+ }
190
218
  };
219
+ if (isLoadingProduct) {
220
+ return _jsx("div", { className: "min-h-screen bg-white flex items-center justify-center p-8", children: "Loading product..." });
221
+ }
191
222
  if (!product) {
192
223
  return (_jsx("div", { className: "min-h-screen bg-white flex items-center justify-center p-8", children: _jsxs("div", { className: "text-center", children: [_jsx("h1", { className: "text-2xl font-bold mb-2", children: "Product Not Found" }), _jsx("p", { className: "text-gray-600 mb-4", children: "The product you're looking for doesn't exist." })] }) }));
193
224
  }
194
- const displayPrice = resolveVariantPrice(product, matchingVariation);
195
- const displaySKU = resolveVariantSKU(product, matchingVariation);
196
- const stockProduct = resolveVariantStockProduct(product, matchingVariation);
225
+ // Use SKU for display, fallback to generated SKU from slug if not available
226
+ const displaySKU = product.sku || product.slug?.toUpperCase().replace(/-/g, '').substring(0, 12).padEnd(8, 'X') || 'N/A';
197
227
  // Build category breadcrumb path with all parent categories
198
228
  const buildCategoryPath = (categoryId) => {
199
229
  if (!categoryId)
@@ -228,9 +258,6 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
228
258
  // but handle edge cases where it might still be in object format
229
259
  // Use the comprehensive extraction utility from store-config-utils for consistency
230
260
  const productImages = (() => {
231
- const variantImages = resolveVariantImageUrls(matchingVariation);
232
- if (variantImages.length > 0)
233
- return variantImages;
234
261
  // Debug: Log the raw product.images to understand its format
235
262
  if (process.env.NODE_ENV === 'development') {
236
263
  console.log('[ProductDetailPage] Raw product.images:', {
@@ -266,10 +293,8 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
266
293
  }
267
294
  return extracted;
268
295
  })();
296
+ // For gallery, use actual images only (don't duplicate to fill 5 slots)
269
297
  const displayImages = productImages.slice(0, 5);
270
- useEffect(() => {
271
- setSelectedImage(0);
272
- }, [matchingVariation?.id, productImages[0]]);
273
298
  const hasMoreImages = productImages.length > 5;
274
299
  // Debug logging for images (can be removed in production)
275
300
  if (process.env.NODE_ENV === 'development') {
@@ -306,16 +331,18 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
306
331
  'Navy': '#1E3A8A',
307
332
  'Beige': '#F5F5DC',
308
333
  };
309
- // Get reviews
310
- const reviews = product.reviews || [];
334
+ // Reviews loaded from API (product payload does not include review rows)
311
335
  const displayedReviews = showAllReviews ? reviews : reviews.slice(0, 3);
312
336
  const hasMoreReviews = reviews.length > 3;
313
- const stockInfo = getProductStockInfo(stockProduct);
314
- const isOutOfStock = !stockInfo.canPurchase;
315
- const maxPurchasableQty = getMaxPurchasableQuantity({ ...product, ...stockProduct });
337
+ const reviewCount = Math.max(Number(product.reviewCount) || 0, reviews.length);
338
+ const averageRating = reviews.length > 0
339
+ ? reviews.reduce((sum, review) => sum + review.rating, 0) / reviews.length
340
+ : Number(product.rating) || 0;
341
+ // Out of stock check
342
+ const isOutOfStock = !product.inStock;
316
343
  // Calculate rating distribution
317
344
  const ratingDistribution = [5, 4, 3, 2, 1].map(rating => {
318
- const count = reviews.filter(r => r.rating === rating).length;
345
+ const count = reviews.filter(r => Math.round(r.rating) === rating).length;
319
346
  return {
320
347
  rating,
321
348
  count,
@@ -324,43 +351,31 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
324
351
  });
325
352
  const handleAddToCart = () => {
326
353
  if (isOutOfStock) {
327
- addToast(formatStockLimitMessage(product.name, stockInfo.availableStock ?? 0), 'error');
328
- return;
329
- }
330
- if (hasVariations && hasSelectedOptions && !matchingVariation) {
331
- addToast('Please select all product options', 'error');
354
+ addToast('This product is currently out of stock', 'error');
332
355
  return;
333
356
  }
334
357
  // Find the matching variation UUID based on selected attributes
335
358
  // Note: StoreProduct uses 'variants' not 'variations'
336
- let variationId = matchingVariation?.id;
337
- if (!variationId && product.variants && product.variants.length > 0) {
338
- const resolved = findMatchingVariation(product.variants, {
339
- ...(selectedColor ? { color: selectedColor } : {}),
340
- ...(selectedSize ? { size: selectedSize } : {}),
341
- ...selectedAttributes,
359
+ let variationId;
360
+ if (product.variants && Array.isArray(product.variants) && product.variants.length > 0) {
361
+ const matchingVariation = product.variants.find((variation) => {
362
+ const attrs = variation.attributes || {};
363
+ const colorMatch = !selectedColor || attrs.color === selectedColor;
364
+ const sizeMatch = !selectedSize || attrs.size === selectedSize;
365
+ return colorMatch && sizeMatch;
342
366
  });
343
- variationId = resolved?.id;
367
+ variationId = matchingVariation?.id;
344
368
  }
369
+ // Fallback to composite string for backward compatibility if no variation found
345
370
  const variantId = variationId || (selectedColor || selectedSize
346
371
  ? [selectedColor, selectedSize].filter(Boolean).join(' / ')
347
372
  : undefined);
348
- const resolvedVariation = variationId ? product.variants?.find(v => v.id === variationId) : matchingVariation;
349
- const variantName = resolvedVariation?.value || Object.values(resolvedVariation?.attributes || {}).filter(Boolean).join(' / ') || undefined;
350
- const unitPrice = resolvedVariation?.price ?? product.price;
351
- addToCart(product, quantity, { variantId, variantName, unitPrice });
373
+ addToCart(product, quantity, variantId);
352
374
  addToast(`${product.name} added to cart`, 'success');
353
375
  };
354
376
  const handleBuyNow = async () => {
355
377
  if (isOutOfStock) {
356
- addToast(formatStockLimitMessage(product.name, stockInfo.availableStock ?? 0), 'error');
357
- return;
358
- }
359
- if (hasVariations && hasSelectedOptions && !matchingVariation) {
360
- addToast('Please select all product options', 'error');
361
- return;
362
- }
363
- if (!guardCheckoutAvailable(storeConfig, addToast)) {
378
+ addToast('This product is currently out of stock', 'error');
364
379
  return;
365
380
  }
366
381
  if (isBuyNowLoading || isCartLoading) {
@@ -370,20 +385,19 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
370
385
  try {
371
386
  // Find the matching variation UUID based on selected attributes
372
387
  // Note: StoreProduct uses 'variants' not 'variations'
373
- let variationId = matchingVariation?.id;
388
+ let variationId;
374
389
  let variantName;
375
- if (!variationId && product.variants && product.variants.length > 0) {
376
- const resolved = findMatchingVariation(product.variants, {
377
- ...(selectedColor ? { color: selectedColor } : {}),
378
- ...(selectedSize ? { size: selectedSize } : {}),
379
- ...selectedAttributes,
390
+ if (product.variants && Array.isArray(product.variants) && product.variants.length > 0) {
391
+ const matchingVariation = product.variants.find((variation) => {
392
+ const attrs = variation.attributes || {};
393
+ const colorMatch = !selectedColor || attrs.color === selectedColor;
394
+ const sizeMatch = !selectedSize || attrs.size === selectedSize;
395
+ return colorMatch && sizeMatch;
380
396
  });
381
- variationId = resolved?.id;
382
- variantName = resolved?.value || Object.values(resolved?.attributes || {}).filter(Boolean).join(' / ');
383
- }
384
- else if (matchingVariation) {
385
- variantName = matchingVariation.value || Object.values(matchingVariation.attributes || {}).filter(Boolean).join(' / ');
397
+ variationId = matchingVariation?.id;
398
+ variantName = matchingVariation?.name || matchingVariation?.value;
386
399
  }
400
+ // Fallback to composite string for backward compatibility if no variation found
387
401
  const variantId = variationId || (selectedColor || selectedSize
388
402
  ? [selectedColor, selectedSize].filter(Boolean).join(' / ')
389
403
  : undefined);
@@ -395,8 +409,8 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
395
409
  quantity,
396
410
  variantId,
397
411
  variantName: variantName || variantId,
398
- price: (variationId ? product.variants?.find(v => v.id === variationId)?.price : matchingVariation?.price) ?? product.price,
399
- product: buildCartLineProduct(product, variationId ? product.variants?.find(v => v.id === variationId) : matchingVariation)
412
+ price: product.price,
413
+ product
400
414
  };
401
415
  // Set buy now item and navigate directly to checkout
402
416
  setBuyNowItem(buyNowItem);
@@ -418,6 +432,44 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
418
432
  // Note: This is now only used for other flows, not buy now
419
433
  // Buy now now redirects to checkout page
420
434
  };
435
+ // Calculate shipping when address is provided
436
+ const calculateShipping = async () => {
437
+ if (!product || !shippingAddress.country || !shippingAddress.city) {
438
+ setShippingError('Please provide country and city to calculate shipping');
439
+ return;
440
+ }
441
+ setIsCalculatingShipping(true);
442
+ setShippingError(null);
443
+ try {
444
+ const currency = product.currency || storeConfig.settings?.currency || 'USD';
445
+ const subtotal = product.price * quantity;
446
+ const result = await shippingService.calculateShipping({
447
+ storeId: storeConfig.id,
448
+ address: {
449
+ country: shippingAddress.country,
450
+ city: shippingAddress.city,
451
+ zipCode: shippingAddress.zipCode,
452
+ },
453
+ items: [{
454
+ productId: product.id,
455
+ quantity: quantity,
456
+ }],
457
+ subtotal: subtotal,
458
+ currency: currency,
459
+ });
460
+ setShippingMethods(result.methods || []);
461
+ setFreeShippingEligible(result.freeShippingEligible || false);
462
+ setFreeShippingThreshold(result.freeShippingThreshold);
463
+ }
464
+ catch (error) {
465
+ console.error('Shipping calculation error:', error);
466
+ setShippingError(error.message || 'Failed to calculate shipping. Please try again.');
467
+ setShippingMethods([]);
468
+ }
469
+ finally {
470
+ setIsCalculatingShipping(false);
471
+ }
472
+ };
421
473
  // Load saved addresses for authenticated users and auto-populate shipping address
422
474
  useEffect(() => {
423
475
  const loadAddresses = async () => {
@@ -425,28 +477,39 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
425
477
  try {
426
478
  const addresses = await customerService.getAddresses();
427
479
  setSavedAddresses(addresses);
480
+ // Auto-populate with default address or first address if available
428
481
  if (addresses.length > 0) {
429
- const defaultAddress = addresses.find((a) => a.isDefault) || addresses[0];
482
+ const defaultAddress = addresses.find(a => a.isDefault) || addresses[0];
430
483
  if (defaultAddress) {
431
- updateShippingAddress(enrichShippingQuoteAddress({
484
+ setShippingAddress({
432
485
  country: defaultAddress.country || '',
433
486
  city: defaultAddress.city || '',
434
487
  zipCode: defaultAddress.zipCode || '',
435
- street: defaultAddress.address1 || '',
436
- state: defaultAddress.state || '',
437
- phone: defaultAddress.phone || '',
438
- }));
488
+ });
439
489
  }
440
490
  }
441
491
  }
442
492
  catch (error) {
443
493
  console.error('Failed to load addresses:', error);
494
+ // Don't show error toast - addresses are optional
495
+ // Users can still manually enter shipping address
444
496
  }
445
497
  }
446
498
  };
447
499
  loadAddresses();
448
500
  // eslint-disable-next-line react-hooks/exhaustive-deps
449
501
  }, [isAuthenticated]);
502
+ // Auto-calculate shipping when address fields are filled (debounced)
503
+ useEffect(() => {
504
+ if (!shippingAddress.country || !shippingAddress.city || !product) {
505
+ return;
506
+ }
507
+ const timer = setTimeout(() => {
508
+ calculateShipping();
509
+ }, 500); // Debounce 500ms
510
+ return () => clearTimeout(timer);
511
+ // eslint-disable-next-line react-hooks/exhaustive-deps
512
+ }, [shippingAddress.country, shippingAddress.city, shippingAddress.zipCode, quantity, product?.id, product?.price]);
450
513
  // Track product view
451
514
  useEffect(() => {
452
515
  if (product && storeConfig?.id) {
@@ -459,48 +522,23 @@ export function FoodProductDetailPage({ storeConfig, productSlug }) {
459
522
  price: product.price,
460
523
  },
461
524
  });
462
- trackStorefrontEvent('Product_viewed', {
463
- storeId: storeConfig.id,
464
- storeSlug: storeConfig.slug,
465
- productId: product.id,
466
- productName: product.name,
467
- categoryId: product.categoryId,
468
- price: product.price,
469
- });
470
525
  }
471
526
  }, [product?.id, storeConfig?.id, trackEvent]);
472
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "min-h-screen bg-white", children: _jsxs("div", { "data-content-ready": true, "data-section": "menuItemInfo", "data-payaza-section-key": "menuItemInfo", "data-payaza-page": "productDetail", className: "container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-7xl", children: [menuItemConfig?.showBreadcrumb !== false && (_jsx("div", { className: "mb-6", children: _jsx(Breadcrumbs, { items: breadcrumbItems }) })), _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 mb-20", children: [_jsxs("div", { className: "relative lg:sticky lg:top-24 self-start z-0", children: [_jsxs("div", { className: "relative aspect-square bg-gray-50 rounded-xl overflow-hidden mb-4 border border-gray-100 shadow-sm group", children: [_jsx(ImageWithFallback, { "data-product-image": true, src: displayImages[selectedImage] || displayImages[0] || productImages[0], alt: product.name, className: cn("w-full h-full object-cover transition-transform duration-300 group-hover:scale-105", isOutOfStock && "grayscale"), skeletonAspectRatio: "square" }), isOutOfStock && (_jsx(OutOfStockOverlay, { badgePosition: "center" }))] }), displayImages.length > 0 && (_jsxs("div", { className: "grid grid-cols-5 gap-2", children: [displayImages.map((image, index) => (_jsx("button", { onClick: () => setSelectedImage(Math.min(index, displayImages.length - 1)), className: `aspect-square rounded-lg overflow-hidden border-2 transition-all ${selectedImage === index
527
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "min-h-screen bg-white", children: _jsxs("div", { "data-content-ready": true, className: "container mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12 max-w-7xl", children: [_jsx("div", { className: "mb-6", children: _jsx(Breadcrumbs, { items: breadcrumbItems }) }), _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 mb-20", children: [_jsxs("div", { className: "relative lg:sticky lg:top-24 self-start z-0", children: [_jsxs("div", { className: "relative aspect-square bg-gray-50 rounded-xl overflow-hidden mb-4 border border-gray-100 shadow-sm group", children: [_jsx(ImageWithFallback, { "data-product-image": true, src: displayImages[selectedImage] || displayImages[0] || productImages[0], alt: product.name, className: cn("w-full h-full object-cover transition-transform duration-300 group-hover:scale-105", isOutOfStock && "grayscale"), skeletonAspectRatio: "square" }), isOutOfStock && (_jsx(OutOfStockOverlay, { badgePosition: "center" }))] }), displayImages.length > 0 && (_jsxs("div", { className: "grid grid-cols-5 gap-2", children: [displayImages.map((image, index) => (_jsx("button", { onClick: () => setSelectedImage(Math.min(index, displayImages.length - 1)), className: `aspect-square rounded-lg overflow-hidden border-2 transition-all ${selectedImage === index
473
528
  ? 'border-gray-900 ring-2 ring-gray-900 ring-offset-2'
474
- : 'border-gray-200 hover:border-gray-300'}`, children: _jsx(ImageWithFallback, { src: image, alt: `${product.name} view ${index + 1}`, className: cn("w-full h-full object-cover", isOutOfStock && "grayscale"), skeletonAspectRatio: "square" }) }, index))), hasMoreImages && (_jsxs("div", { className: "aspect-square rounded-lg border-2 border-gray-200 bg-gray-50 flex items-center justify-center text-xs text-gray-500 font-medium", children: ["+", productImages.length - 5, " more"] }))] }))] }), _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsx("span", { className: "text-sm font-semibold text-gray-700 uppercase tracking-wide", children: directCategory?.name || storeConfig.name }), _jsx("button", { onClick: handleShare, className: "text-gray-400 hover:text-gray-900 transition-colors p-2 rounded-full hover:bg-gray-100", title: "Share this product", children: _jsx(Share2, { className: "h-5 w-5" }) })] }), _jsx("h1", { "data-product-name": true, className: "text-3xl sm:text-4xl lg:text-5xl font-bold text-gray-900 mb-3 leading-tight tracking-tight", children: product.name }), _jsxs("p", { className: "text-sm text-gray-500 mb-6 font-mono", children: ["SKU: ", displaySKU] }), _jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsx(ProductStockBadge, { product: stockProduct }), _jsx(LimitedTimeOfferBadge, { product: product })] }), _jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-baseline gap-4", children: [_jsx("span", { "data-product-price": true, className: "text-4xl lg:text-5xl font-bold text-gray-900", children: formatCurrency(matchingVariation?.price ?? product.price, product.currency || 'USD') }), (matchingVariation?.compareAtPrice ?? product.compareAtPrice) != null &&
475
- (matchingVariation?.compareAtPrice ?? product.compareAtPrice) >
476
- (matchingVariation?.price ?? product.price) && (_jsx("span", { className: "text-2xl text-gray-500 line-through", children: formatCurrency(matchingVariation?.compareAtPrice ?? product.compareAtPrice, product.currency || 'USD') }))] }), (matchingVariation?.compareAtPrice ?? product.compareAtPrice) != null &&
477
- (matchingVariation?.compareAtPrice ?? product.compareAtPrice) >
478
- (matchingVariation?.price ?? product.price) && (_jsxs("span", { className: "inline-block mt-2 bg-red-100 text-red-700 text-xs font-bold px-2 py-1 rounded", children: ["SAVE", " ", Math.round((((matchingVariation?.compareAtPrice ?? product.compareAtPrice) -
479
- (matchingVariation?.price ?? product.price)) /
480
- (matchingVariation?.compareAtPrice ?? product.compareAtPrice)) *
481
- 100), "%"] }))] }), _jsx(ProductVariationSelectors, { optionGroups: optionGroups, selectedAttributes: selectedAttributes, onSelectAttribute: setAttribute, storeSlug: storeConfig.slug, colorSwatches: colorSwatches, variants: product.variants }), _jsxs("div", { className: "flex flex-col gap-4 mb-8", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: "Quantity" }), _jsxs("div", { className: "flex items-center border border-gray-300 rounded-lg", children: [_jsx("button", { className: "p-3 text-gray-600 hover:bg-gray-100 rounded-l-lg disabled:opacity-50", onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1, children: _jsx(Minus, { className: "h-4 w-4" }) }), _jsx("span", { className: "w-12 text-center font-semibold text-gray-900", children: quantity }), _jsx("button", { className: "p-3 text-gray-600 hover:bg-gray-100 rounded-r-lg disabled:opacity-50", onClick: () => setQuantity(Math.min(maxPurchasableQty ?? quantity + 1, quantity + 1)), disabled: maxPurchasableQty != null && quantity >= maxPurchasableQty, children: _jsx(Plus, { className: "h-4 w-4" }) })] })] }), _jsxs("div", { className: "flex flex-col sm:flex-row gap-3 mt-2", children: [_jsx(Button, { "data-add-to-cart": true, size: "xl", onClick: handleAddToCart, disabled: isCartLoading || isOutOfStock, className: "w-full sm:flex-1 bg-white border-2 border-gray-900 text-gray-900 hover:bg-gray-50 rounded-full min-h-14 text-base font-bold shadow-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed", children: isCartLoading ? (_jsxs(_Fragment, { children: [_jsx(ButtonLoader, { className: "mr-2" }), "Adding..."] })) : (_jsxs(_Fragment, { children: [_jsx(ShoppingCart, { className: "h-5 w-5 mr-2" }), _jsx("span", { ...payazaInlineBindingProps(isPreview, 'menuItemInfo', ['addToCartText']), children: menuItemConfig?.addToCartText || "Add to Cart" })] })) }), _jsx(Button, { size: "xl", onClick: handleBuyNow, disabled: isOutOfStock || isBuyNowLoading || isCartLoading || isCheckoutDisabled(storeConfig), className: "w-full sm:flex-1 bg-gray-900 hover:bg-gray-800 text-white rounded-full min-h-14 text-base font-bold shadow-lg hover:shadow-xl transition-all disabled:opacity-50 disabled:cursor-not-allowed", children: isBuyNowLoading || isCartLoading ? (_jsxs(_Fragment, { children: [_jsx(ButtonLoader, { className: "mr-2" }), "Adding..."] })) : (_jsx("span", { ...payazaInlineBindingProps(isPreview, 'menuItemInfo', ['buyNowText']), children: menuItemConfig?.buyNowText || "Buy Now" })) }), storeConfig.features.wishlist && (_jsx(Button, { variant: "outline", size: "xl", onClick: handleWishlistClick, disabled: isWishlistLoading || !product, className: cn("h-14 w-14 rounded-full border-2 transition-all disabled:opacity-50 disabled:cursor-not-allowed", product && isInWishlist(product.id)
529
+ : 'border-gray-200 hover:border-gray-300'}`, children: _jsx(ImageWithFallback, { src: image, alt: `${product.name} view ${index + 1}`, className: cn("w-full h-full object-cover", isOutOfStock && "grayscale"), skeletonAspectRatio: "square" }) }, index))), hasMoreImages && (_jsxs("div", { className: "aspect-square rounded-lg border-2 border-gray-200 bg-gray-50 flex items-center justify-center text-xs text-gray-500 font-medium", children: ["+", productImages.length - 5, " more"] }))] }))] }), _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsx("span", { className: "text-sm font-semibold text-gray-700 uppercase tracking-wide", children: directCategory?.name || storeConfig.name }), _jsx("button", { onClick: handleShare, className: "text-gray-400 hover:text-gray-900 transition-colors p-2 rounded-full hover:bg-gray-100", title: "Share this product", children: _jsx(Share2, { className: "h-5 w-5" }) })] }), _jsx("h1", { "data-product-name": true, className: "text-3xl sm:text-4xl lg:text-5xl font-bold text-gray-900 mb-3 leading-tight tracking-tight", children: product.name }), _jsxs("p", { className: "text-sm text-gray-500 mb-6 font-mono", children: ["SKU: ", displaySKU] }), _jsx("div", { className: "mb-4 flex items-center gap-2", children: product.inStock ? (_jsxs("span", { className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800", children: [_jsx(CheckCircle, { className: "w-3 h-3 mr-1" }), "In Stock"] })) : (_jsxs("span", { className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800", children: [_jsx(Info, { className: "w-3 h-3 mr-1" }), "Out of Stock"] })) }), _jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-baseline gap-4", children: [_jsx("span", { "data-product-price": true, className: "text-4xl lg:text-5xl font-bold text-gray-900", children: formatCurrency(product.price, product.currency || 'USD') }), product.compareAtPrice && (_jsx("span", { className: "text-2xl text-gray-500 line-through", children: formatCurrency(product.compareAtPrice, product.currency || 'USD') }))] }), product.compareAtPrice && (_jsxs("span", { className: "inline-block mt-2 bg-red-100 text-red-700 text-xs font-bold px-2 py-1 rounded", children: ["SAVE ", Math.round(((product.compareAtPrice - product.price) / product.compareAtPrice) * 100), "%"] }))] }), colorVariants.length > 0 && (_jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-center gap-2 mb-4", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: "Color:" }), _jsx("span", { className: "text-sm text-gray-600 capitalize", children: selectedColor || colorVariants[0]?.value })] }), _jsx("div", { className: "flex gap-3", children: colorVariants.map((variant) => {
530
+ const colorValue = variant.value;
531
+ const swatchColor = colorSwatches[colorValue] || '#CCCCCC';
532
+ const isSelected = selectedColor === colorValue;
533
+ return (_jsx("button", { onClick: () => setSelectedColor(colorValue), className: `relative w-12 h-12 rounded-full border-2 transition-all ${isSelected
534
+ ? 'border-gray-900 ring-2 ring-gray-900 ring-offset-2 scale-105'
535
+ : 'border-gray-200 hover:border-gray-300'}`, style: { backgroundColor: swatchColor }, title: colorValue, children: isSelected && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx(CheckCircle, { className: `h-5 w-5 ${['White', 'Beige', 'Yellow'].includes(colorValue) ? 'text-gray-900' : 'text-white'} drop-shadow-sm` }) })) }, variant.id));
536
+ }) })] })), sizeVariants.length > 0 && (_jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: "Size:" }), _jsx("span", { className: "text-sm text-gray-600", children: selectedSize || 'Select Size' })] }), _jsxs("a", { href: `/${storeConfig.slug}/size-guide`, target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-1.5 text-xs font-medium text-gray-600 hover:text-gray-900 underline decoration-gray-400 underline-offset-4", children: [_jsx(Ruler, { className: "h-3.5 w-3.5" }), " Size guide"] })] }), _jsx("div", { className: "grid grid-cols-4 sm:grid-cols-5 gap-2.5", children: sizeVariants.map((variant) => {
537
+ const isSelected = selectedSize === variant.value;
538
+ return (_jsx("button", { onClick: () => setSelectedSize(variant.value), className: `px-4 py-3 rounded-lg border-2 text-sm font-semibold transition-all ${isSelected
539
+ ? 'bg-gray-900 text-white border-gray-900 shadow-md transform -translate-y-0.5'
540
+ : 'bg-white text-gray-700 border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: variant.value }, variant.id));
541
+ }) })] })), _jsxs("div", { className: "flex flex-col gap-4 mb-8", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: "Quantity" }), _jsxs("div", { className: "flex items-center border border-gray-300 rounded-lg", children: [_jsx("button", { className: "p-3 text-gray-600 hover:bg-gray-100 rounded-l-lg disabled:opacity-50", onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1, children: _jsx(Minus, { className: "h-4 w-4" }) }), _jsx("span", { className: "w-12 text-center font-semibold text-gray-900", children: quantity }), _jsx("button", { className: "p-3 text-gray-600 hover:bg-gray-100 rounded-r-lg", onClick: () => setQuantity(quantity + 1), children: _jsx(Plus, { className: "h-4 w-4" }) })] })] }), _jsxs("div", { className: "flex flex-col sm:flex-row gap-3 mt-2", children: [_jsx(Button, { "data-add-to-cart": true, size: "lg", onClick: handleAddToCart, disabled: isCartLoading || isOutOfStock, className: "flex-1 bg-white border-2 border-gray-900 text-gray-900 hover:bg-gray-50 rounded-full h-14 text-base font-bold shadow-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed", children: isCartLoading ? (_jsxs(_Fragment, { children: [_jsx(ButtonLoader, { className: "mr-2" }), "Adding..."] })) : (_jsxs(_Fragment, { children: [_jsx(ShoppingCart, { className: "h-5 w-5 mr-2" }), "Add to Cart"] })) }), _jsx(Button, { size: "lg", onClick: handleBuyNow, disabled: isOutOfStock || isBuyNowLoading || isCartLoading, className: "flex-1 bg-gray-900 hover:bg-gray-800 text-white rounded-full h-14 text-base font-bold shadow-lg hover:shadow-xl transition-all disabled:opacity-50 disabled:cursor-not-allowed", children: isBuyNowLoading || isCartLoading ? (_jsxs(_Fragment, { children: [_jsx(ButtonLoader, { className: "mr-2" }), "Adding..."] })) : ('Buy Now') }), storeConfig.features.wishlist && (_jsx(Button, { variant: "outline", size: "lg", onClick: handleWishlistClick, disabled: isWishlistLoading || !product, className: cn("h-14 w-14 rounded-full border-2 transition-all disabled:opacity-50 disabled:cursor-not-allowed", product && isInWishlist(product.id)
482
542
  ? "border-red-500 bg-red-50 text-red-500 hover:bg-red-100"
483
- : "border-gray-200 hover:border-gray-300 hover:bg-gray-50"), children: isWishlistLoading ? (_jsx(ButtonLoader, { className: "h-5 w-5" })) : (_jsx(Heart, { className: cn("h-5 w-5", product && isInWishlist(product.id) && "fill-current") })) }))] })] }), _jsxs("div", { className: "mb-8 border-t border-b border-gray-100 py-6", children: [_jsxs("h3", { className: "font-bold text-gray-900 flex items-center gap-2 text-sm mb-4 uppercase tracking-wider", children: [_jsx(Truck, { className: "h-4 w-4" }), " Delivery Information"] }), !isAutomatedShippingEnabled(storeConfig) ? (_jsx(MerchantHandledDeliveryNotice, { storeName: storeConfig.name })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "mb-4 bg-gray-50 p-2 rounded-xl border border-gray-200", children: _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("button", { type: "button", onClick: () => setIsPickup(true), className: cn("flex items-center justify-center gap-2 px-4 py-3 rounded-lg border-2 transition-all font-bold text-sm", isPickup
484
- ? "border-gray-900 bg-gray-900 text-white"
485
- : "border-transparent bg-white text-gray-700 hover:bg-gray-100"), children: [_jsx(MapPin, { className: "w-4 h-4" }), "Pickup"] }), _jsxs("button", { type: "button", onClick: () => setIsPickup(false), className: cn("flex items-center justify-center gap-2 px-4 py-3 rounded-lg border-2 transition-all font-bold text-sm", !isPickup
486
- ? "border-gray-900 bg-gray-900 text-white"
487
- : "border-transparent bg-white text-gray-700 hover:bg-gray-100"), children: [_jsx(Truck, { className: "w-4 h-4" }), "Delivery"] })] }) }), isPickup ? (_jsxs("div", { className: "mb-4 p-4 bg-white rounded-lg border border-gray-200", children: [_jsx("p", { className: "text-xs font-semibold text-gray-700 mb-3 uppercase tracking-wider", children: "Select Pickup Location" }), isLoadingLocations ? (_jsxs("div", { className: "flex items-center gap-2 py-4 justify-center", children: [_jsx(ButtonLoader, { className: "h-4 w-4" }), _jsx("span", { className: "text-xs text-gray-500", children: "Loading locations..." })] })) : locations.length > 0 ? (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "relative", children: [_jsx("select", { className: "w-full px-3 py-2 text-sm bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-transparent transition-all font-medium appearance-none", value: selectedLocation?.id || '', onChange: (e) => {
488
- const location = locations.find(l => l.id === e.target.value);
489
- if (location)
490
- setSelectedLocation(location);
491
- }, children: locations.map(location => (_jsx("option", { value: location.id, children: location.name }, location.id))) }), _jsx(ChevronDown, { className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 pointer-events-none" })] }), selectedLocation && (_jsxs("div", { className: "p-3 bg-gray-50 rounded-lg border border-gray-100 space-y-1", children: [_jsx("p", { className: "text-sm font-bold text-gray-900", children: selectedLocation.name }), _jsx("p", { className: "text-xs text-gray-600", children: [
492
- selectedLocation.address.street,
493
- selectedLocation.address.city,
494
- selectedLocation.address.state
495
- ].filter(Boolean).join(', ') }), selectedLocation.phone && (_jsxs("p", { className: "text-xs text-blue-600 font-medium", children: ["\uD83D\uDCDE ", selectedLocation.phone] })), _jsx("p", { className: "text-[10px] text-green-600 font-bold uppercase mt-1", children: "\u2713 Ready for pickup in 2-4 hours" })] }))] })) : (_jsxs("div", { className: "p-3 bg-blue-50 border border-blue-100 rounded-lg", children: [_jsx("p", { className: "text-xs text-blue-800", children: "Please use our main store address for pickup or select delivery." }), storeConfig.contactInfo?.address && (_jsxs("div", { className: "mt-2 text-xs text-blue-700", children: [_jsx("p", { className: "font-bold", children: storeConfig.name }), _jsx("p", { children: typeof storeConfig.contactInfo.address === 'string' ? storeConfig.contactInfo.address : storeConfig.contactInfo.address.street })] }))] }))] })) : (_jsxs("div", { className: "mb-4 p-4 bg-gray-50 rounded-lg border border-gray-200", children: [_jsx("p", { className: "text-xs font-semibold text-gray-700 mb-3 uppercase tracking-wider", children: "Calculate Shipping" }), _jsx(ShippingQuoteAddressForm, { address: shippingAddress, onChange: updateShippingAddress, onToast: (message, type) => addToast(message, type) }), shippingError && (_jsx("p", { className: "text-xs text-red-600 mt-2", children: shippingError }))] })), freeShippingThreshold !== undefined && !freeShippingEligible && (_jsxs("div", { className: "mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg", children: [_jsxs("p", { className: "text-xs font-medium text-blue-900 mb-1", children: ["Spend ", formatCurrency(freeShippingThreshold - (displayPrice * quantity), product.currency || storeConfig.settings?.currency || 'USD'), " more for free shipping!"] }), _jsx("div", { className: "w-full bg-blue-200 rounded-full h-2", children: _jsx("div", { className: "bg-blue-600 h-2 rounded-full transition-all", style: {
496
- width: `${Math.min(100, ((displayPrice * quantity) / freeShippingThreshold) * 100)}%`,
497
- } }) })] })), isCalculatingShipping ? (_jsx("div", { className: "flex items-center justify-center p-8", children: _jsxs("div", { className: "flex items-center gap-2 text-gray-600", children: [_jsx("div", { className: "animate-spin rounded-full h-5 w-5 border-b-2 border-gray-900" }), _jsx("span", { className: "text-sm font-medium", children: "Calculating shipping..." })] }) })) : shippingMethods.length > 0 ? (_jsx("div", { className: "space-y-0 divide-y divide-gray-100 border border-gray-100 rounded-lg overflow-hidden", children: shippingMethods.map((method, index) => (_jsxs("div", { className: cn("flex items-center justify-between p-4 bg-white hover:bg-gray-50 transition-colors group", freeShippingEligible && method.cost === 0 && "bg-green-50 border-green-200"), children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn("p-2 rounded-full group-hover:bg-white transition-colors border", freeShippingEligible && method.cost === 0
498
- ? "bg-green-100 border-green-300"
499
- : "bg-gray-50 border-gray-100"), children: freeShippingEligible && method.cost === 0 ? (_jsx(CheckCircle, { className: "h-4 w-4 text-green-700" })) : (_jsx(Truck, { className: "h-4 w-4 text-gray-900" })) }), _jsxs("div", { children: [_jsxs("p", { className: "font-bold text-gray-900 text-sm", children: [method.name, freeShippingEligible && method.cost === 0 && (_jsx("span", { className: "ml-2 text-xs font-normal text-green-700 bg-green-100 px-2 py-0.5 rounded-full", children: "FREE" }))] }), _jsx("p", { className: "text-[11px] text-gray-500 font-medium mt-0.5", children: method.description || method.estimatedDays
500
- ? `${method.estimatedDaysMin || method.estimatedDays}-${method.estimatedDaysMax || method.estimatedDays} business days`
501
- : 'Delivery estimate available' })] })] }), _jsxs("div", { className: "text-right", children: [_jsx("p", { className: "font-bold text-gray-900 text-sm", children: freeShippingEligible && method.cost === 0
502
- ? 'FREE'
503
- : formatCurrency(method.cost, product.currency || storeConfig.settings?.currency || 'USD') }), method.estimatedDays && (_jsx("p", { className: "text-[11px] text-gray-500 font-medium mt-0.5", children: method.estimatedDaysMin && method.estimatedDaysMax
504
- ? `${method.estimatedDaysMin}-${method.estimatedDaysMax} days`
505
- : `${method.estimatedDays} days` }))] })] }, method.code || index))) })) : shippingAddress.country && shippingAddress.city ? (_jsx("div", { className: "p-4 bg-gray-50 border border-gray-200 rounded-lg text-center", children: _jsx("p", { className: "text-sm text-gray-600", children: "No shipping methods available for this location." }) })) : (_jsx("div", { className: "p-4 bg-gray-50 border border-gray-200 rounded-lg text-center", children: _jsx("p", { className: "text-sm text-gray-600", children: "Enter your address above to see shipping options." }) }))] }))] }), _jsx(ProductDescription, { description: product.description }), product.specifications && Object.keys(product.specifications).length > 0 && (_jsxs("div", { className: "mb-8", children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-4", children: "Specifications" }), _jsx("dl", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-4", children: Object.entries(product.specifications).map(([key, value]) => (_jsxs("div", { className: "flex flex-col p-3 bg-gray-50 rounded-lg", children: [_jsx("dt", { className: "text-xs text-gray-500 font-medium uppercase tracking-wider mb-1", children: key }), _jsx("dd", { className: "text-sm font-bold text-gray-900", children: value })] }, key))) })] }))] })] }), _jsx("div", { className: "mt-20 pt-16 border-t border-gray-200", children: _jsxs("div", { className: "max-w-4xl", children: [_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 mb-10", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-2xl lg:text-3xl font-bold text-gray-900 mb-4", children: "Customer Reviews" }), product.reviewCount && product.reviewCount > 0 && product.rating && product.rating > 0 ? (_jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StarRating, { rating: typeof product.rating === 'number' ? product.rating : Number(product.rating) || 0, size: "lg" }), _jsx("span", { className: "text-2xl font-bold text-gray-900", children: Number(product.rating).toFixed(1) }), _jsx("span", { className: "text-lg text-gray-500", children: "out of 5" })] }), _jsx("span", { className: "text-gray-300", children: "|" }), _jsxs("span", { className: "text-lg text-gray-600", children: [product.reviewCount, " ", product.reviewCount === 1 ? 'review' : 'reviews'] })] })) : (_jsx("div", { className: "text-gray-500", children: _jsx("p", { className: "text-base", children: "Be the first to review this product" }) }))] }), _jsx(Button, { onClick: () => setIsReviewModalOpen(true), className: "rounded-full shrink-0 bg-gray-900 hover:bg-gray-800 text-white", children: product.reviewCount && product.reviewCount > 0 ? 'Write a Review' : 'Be the First to Review' })] }), ratingDistribution.some(r => r.count > 0) && (_jsxs("div", { className: "mb-10 p-6 bg-gray-50 rounded-xl border border-gray-100", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-5", children: "Rating Breakdown" }), _jsx("div", { className: "space-y-3", children: ratingDistribution.map(({ rating, count, percentage }) => (_jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-1.5 w-20", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: rating }), _jsx(Star, { className: "h-4 w-4 fill-gray-900 text-gray-900" })] }), _jsx("div", { className: "flex-1 h-2.5 bg-gray-200 rounded-full overflow-hidden", children: _jsx("div", { className: "h-full bg-gradient-to-r from-gray-700 to-gray-900 rounded-full transition-all duration-500", style: { width: `${percentage}%` } }) }), _jsx("span", { className: "text-sm font-medium text-gray-700 w-12 text-right", children: count })] }, rating))) })] })), reviews.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "space-y-6", children: displayedReviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) }), hasMoreReviews && !showAllReviews && (_jsx("div", { className: "mt-8 text-center", children: _jsxs(Button, { variant: "outline", onClick: () => setShowAllReviews(true), className: "px-8 rounded-full h-12 border-gray-300", children: ["Show All ", reviews.length, " Reviews"] }) }))] })) : (_jsxs("div", { className: "text-center py-12 bg-gray-50 rounded-xl border border-dashed border-gray-300", children: [_jsx("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-sm mb-4", children: _jsx(Star, { className: "h-6 w-6 text-gray-400" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "No Reviews Yet" }), _jsx("p", { className: "text-gray-500 max-w-sm mx-auto mb-6", children: "Be the first to review this product and help other customers make informed decisions." }), _jsx(Button, { onClick: () => setIsReviewModalOpen(true), className: "bg-gray-900 hover:bg-gray-800 text-white", children: "Write the First Review" })] }))] }) }), relatedProducts.length > 0 && menuItemConfig?.showRelated !== false && (_jsxs("div", { className: "mt-20 pt-16 border-t border-gray-200", children: [_jsx("h2", { className: "text-2xl lg:text-3xl font-bold text-gray-900 mb-8", ...payazaInlineBindingProps(isPreview, 'menuItemInfo', ['relatedTitle']), children: menuItemConfig?.relatedTitle || "You Might Also Like" }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6", children: relatedProducts.map((relatedProduct) => (_jsx("div", { className: "h-[400px]", children: _jsx(ProductCard, { product: relatedProduct, storeSlug: storeConfig.slug, onAddToCart: (p) => addToCart(p, 1), onQuickView: handleQuickView, className: "h-full" }) }, relatedProduct.id))) })] }))] }) }), _jsx(Modal, { isOpen: isReviewModalOpen, onClose: () => setIsReviewModalOpen(false), title: "Write a Review", children: _jsxs("form", { onSubmit: handleSubmitReview, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Rating" }), _jsxs("div", { className: "flex items-center gap-1", children: [[1, 2, 3, 4, 5].map((star) => (_jsxs("div", { className: "relative group", children: [_jsx("button", { type: "button", onClick: () => setNewReview({ ...newReview, rating: star - 0.5 }), className: "absolute top-0 left-0 w-1/2 h-full z-20 focus:outline-none", title: `${star - 0.5} stars` }), _jsx("button", { type: "button", onClick: () => setNewReview({ ...newReview, rating: star }), className: "absolute top-0 right-0 w-1/2 h-full z-20 focus:outline-none", title: `${star} stars` }), _jsxs("div", { className: "relative pointer-events-none transition-transform group-hover:scale-110", children: [_jsx(Star, { className: "h-8 w-8 text-gray-200 fill-gray-200" }), newReview.rating >= star - 0.5 && (_jsx("div", { className: "absolute inset-0 overflow-hidden", style: { width: newReview.rating === star - 0.5 ? '50%' : '100%' }, children: _jsx(Star, { className: "h-8 w-8 text-gray-900 fill-gray-900" }) }))] })] }, star))), _jsx("span", { className: "ml-3 text-lg font-medium text-gray-900 w-12", children: newReview.rating })] })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "title", className: "block text-sm font-medium text-gray-700 mb-1", children: "Review Title" }), _jsx("input", { type: "text", id: "title", required: true, className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-black", placeholder: "Summarize your thoughts", value: newReview.title, onChange: (e) => setNewReview({ ...newReview, title: e.target.value }) })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "comment", className: "block text-sm font-medium text-gray-700 mb-1", children: "Review" }), _jsx("textarea", { id: "comment", required: true, rows: 4, className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-black", placeholder: "What did you like or dislike?", value: newReview.comment, onChange: (e) => setNewReview({ ...newReview, comment: e.target.value }) })] }), _jsxs("div", { className: "pt-4 flex justify-end gap-3", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setIsReviewModalOpen(false), children: "Cancel" }), _jsx(Button, { type: "submit", className: "bg-black text-white hover:bg-gray-800", children: "Submit Review" })] })] }) }), _jsx(GuestCheckoutModal, { isOpen: showGuestModal, onClose: () => setShowGuestModal(false), onSubmit: handleGuestInfoSubmit, initialData: getGuestUserInfo() || undefined })] }));
543
+ : "border-gray-200 hover:border-gray-300 hover:bg-gray-50"), children: isWishlistLoading ? (_jsx(ButtonLoader, { className: "h-5 w-5" })) : (_jsx(Heart, { className: cn("h-5 w-5", product && isInWishlist(product.id) && "fill-current") })) }))] })] }), _jsx(ProductDeliveryInfoSection, { storeConfig: storeConfig, currency: storeConfig.settings?.currency || 'USD', productCurrency: product.currency, productPrice: product.price, quantity: quantity, shippingAddress: shippingAddress, updateShippingAddress: (patch) => setShippingAddress((prev) => ({ ...prev, ...patch })), shippingMethods: shippingMethods, isCalculatingShipping: isCalculatingShipping, shippingError: shippingError, freeShippingEligible: freeShippingEligible, freeShippingThreshold: freeShippingThreshold, onToast: addToast }), product.description && (_jsxs("div", { className: "mb-8", children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-3", children: "Description" }), _jsxs("div", { className: "prose prose-sm max-w-none text-gray-600 leading-relaxed", children: [_jsx("p", { children: product.description }), _jsxs("ul", { className: "list-disc pl-5 space-y-1 mt-2", children: [_jsx("li", { children: "Premium quality material" }), _jsx("li", { children: "Comfortable fit for all-day wear" }), _jsx("li", { children: "Durable stitching and finish" })] })] })] })), product.specifications && Object.keys(product.specifications).length > 0 && (_jsxs("div", { className: "mb-8", children: [_jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-4", children: "Specifications" }), _jsx("dl", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-4", children: Object.entries(product.specifications).map(([key, value]) => (_jsxs("div", { className: "flex flex-col p-3 bg-gray-50 rounded-lg", children: [_jsx("dt", { className: "text-xs text-gray-500 font-medium uppercase tracking-wider mb-1", children: key }), _jsx("dd", { className: "text-sm font-bold text-gray-900", children: value })] }, key))) })] }))] })] }), _jsx("div", { className: "mt-20 pt-16 border-t border-gray-200", children: _jsxs("div", { className: "max-w-4xl", children: [_jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-6 mb-10", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h2", { className: "text-2xl lg:text-3xl font-bold text-gray-900 mb-4", children: "Customer Reviews" }), product.reviewCount && product.reviewCount > 0 && product.rating && product.rating > 0 ? (_jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StarRating, { rating: typeof product.rating === 'number' ? product.rating : Number(product.rating) || 0, size: "lg" }), _jsx("span", { className: "text-2xl font-bold text-gray-900", children: Number(product.rating).toFixed(1) }), _jsx("span", { className: "text-lg text-gray-500", children: "out of 5" })] }), _jsx("span", { className: "text-gray-300", children: "|" }), _jsxs("span", { className: "text-lg text-gray-600", children: [product.reviewCount, " ", product.reviewCount === 1 ? 'review' : 'reviews'] })] })) : (_jsx("div", { className: "text-gray-500", children: _jsx("p", { className: "text-base", children: "Be the first to review this product" }) }))] }), _jsx(Button, { onClick: () => setIsReviewModalOpen(true), className: "rounded-full shrink-0 bg-gray-900 hover:bg-gray-800 text-white", children: product.reviewCount && product.reviewCount > 0 ? 'Write a Review' : 'Be the First to Review' })] }), ratingDistribution.some(r => r.count > 0) && (_jsxs("div", { className: "mb-10 p-6 bg-gray-50 rounded-xl border border-gray-100", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-5", children: "Rating Breakdown" }), _jsx("div", { className: "space-y-3", children: ratingDistribution.map(({ rating, count, percentage }) => (_jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-1.5 w-20", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: rating }), _jsx(Star, { className: "h-4 w-4 fill-gray-900 text-gray-900" })] }), _jsx("div", { className: "flex-1 h-2.5 bg-gray-200 rounded-full overflow-hidden", children: _jsx("div", { className: "h-full bg-gradient-to-r from-gray-700 to-gray-900 rounded-full transition-all duration-500", style: { width: `${percentage}%` } }) }), _jsx("span", { className: "text-sm font-medium text-gray-700 w-12 text-right", children: count })] }, rating))) })] })), reviews.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "space-y-6", children: displayedReviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) }), hasMoreReviews && !showAllReviews && (_jsx("div", { className: "mt-8 text-center", children: _jsxs(Button, { variant: "outline", onClick: () => setShowAllReviews(true), className: "px-8 rounded-full h-12 border-gray-300", children: ["Show All ", reviews.length, " Reviews"] }) }))] })) : (_jsxs("div", { className: "text-center py-12 bg-gray-50 rounded-xl border border-dashed border-gray-300", children: [_jsx("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-sm mb-4", children: _jsx(Star, { className: "h-6 w-6 text-gray-400" }) }), _jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "No Reviews Yet" }), _jsx("p", { className: "text-gray-500 max-w-sm mx-auto mb-6", children: "Be the first to review this product and help other customers make informed decisions." }), _jsx(Button, { onClick: () => setIsReviewModalOpen(true), className: "bg-gray-900 hover:bg-gray-800 text-white", children: "Write the First Review" })] }))] }) }), relatedProducts.length > 0 && (_jsxs("div", { className: "mt-20 pt-16 border-t border-gray-200", children: [_jsx("h2", { className: "text-2xl lg:text-3xl font-bold text-gray-900 mb-8", children: "You Might Also Like" }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6", children: relatedProducts.map((relatedProduct) => (_jsx("div", { className: "h-[400px]", children: _jsx(ProductCard, { product: relatedProduct, storeSlug: storeConfig.slug, onAddToCart: (p) => addToCart(p, 1), onQuickView: handleQuickView, className: "h-full" }) }, relatedProduct.id))) })] }))] }) }), _jsx(Modal, { isOpen: isReviewModalOpen, onClose: () => setIsReviewModalOpen(false), title: "Write a Review", children: _jsxs("form", { onSubmit: handleSubmitReview, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Rating" }), _jsxs("div", { className: "flex items-center gap-1", children: [[1, 2, 3, 4, 5].map((star) => (_jsxs("div", { className: "relative group", children: [_jsx("button", { type: "button", onClick: () => setNewReview({ ...newReview, rating: star - 0.5 }), className: "absolute top-0 left-0 w-1/2 h-full z-20 focus:outline-none", title: `${star - 0.5} stars` }), _jsx("button", { type: "button", onClick: () => setNewReview({ ...newReview, rating: star }), className: "absolute top-0 right-0 w-1/2 h-full z-20 focus:outline-none", title: `${star} stars` }), _jsxs("div", { className: "relative pointer-events-none transition-transform group-hover:scale-110", children: [_jsx(Star, { className: "h-8 w-8 text-gray-200 fill-gray-200" }), newReview.rating >= star - 0.5 && (_jsx("div", { className: "absolute inset-0 overflow-hidden", style: { width: newReview.rating === star - 0.5 ? '50%' : '100%' }, children: _jsx(Star, { className: "h-8 w-8 text-gray-900 fill-gray-900" }) }))] })] }, star))), _jsx("span", { className: "ml-3 text-lg font-medium text-gray-900 w-12", children: newReview.rating })] })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "title", className: "block text-sm font-medium text-gray-700 mb-1", children: "Review Title" }), _jsx("input", { type: "text", id: "title", required: true, className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-black", placeholder: "Summarize your thoughts", value: newReview.title, onChange: (e) => setNewReview({ ...newReview, title: e.target.value }) })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "comment", className: "block text-sm font-medium text-gray-700 mb-1", children: "Review" }), _jsx("textarea", { id: "comment", required: true, rows: 4, className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-black", placeholder: "What did you like or dislike?", value: newReview.comment, onChange: (e) => setNewReview({ ...newReview, comment: e.target.value }) })] }), _jsxs("div", { className: "pt-4 flex justify-end gap-3", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setIsReviewModalOpen(false), children: "Cancel" }), _jsx(Button, { type: "submit", className: "bg-black text-white hover:bg-gray-800", children: "Submit Review" })] })] }) }), _jsx(GuestCheckoutModal, { isOpen: showGuestModal, onClose: () => setShowGuestModal(false), onSubmit: handleGuestInfoSubmit, initialData: getGuestUserInfo() || undefined })] }));
506
544
  }