storefront-layouts 1.0.6 → 1.0.7

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 (160) hide show
  1. package/dist/components/ui/route-skeleton-loader.d.ts.map +1 -1
  2. package/dist/components/ui/route-skeleton-loader.js +6 -1
  3. package/dist/editor/alignment-schemas/booking-footer-section.d.ts.map +1 -1
  4. package/dist/editor/alignment-schemas/booking-footer-section.js +0 -1
  5. package/dist/editor/alignment-schemas/clothing.d.ts.map +1 -1
  6. package/dist/editor/alignment-schemas/clothing.js +0 -1
  7. package/dist/editor/alignment-schemas/food.d.ts.map +1 -1
  8. package/dist/editor/alignment-schemas/food.js +0 -1
  9. package/dist/hooks/use-category-products.d.ts +5 -1
  10. package/dist/hooks/use-category-products.d.ts.map +1 -1
  11. package/dist/hooks/use-category-products.js +8 -5
  12. package/dist/hooks/use-filtered-products-fetch.d.ts +12 -0
  13. package/dist/hooks/use-filtered-products-fetch.d.ts.map +1 -0
  14. package/dist/hooks/use-filtered-products-fetch.js +58 -0
  15. package/dist/index.d.ts +5 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +5 -0
  18. package/dist/layouts/booking/components/BookingHomePage.d.ts.map +1 -1
  19. package/dist/layouts/booking/components/BookingHomePage.js +3 -1
  20. package/dist/layouts/booking/pages/AboutPage.d.ts.map +1 -1
  21. package/dist/layouts/booking/pages/AboutPage.js +3 -1
  22. package/dist/layouts/booking/pages/CategoryPage.d.ts.map +1 -1
  23. package/dist/layouts/booking/pages/CategoryPage.js +3 -1
  24. package/dist/layouts/booking/pages/ProductDetailPage.d.ts.map +1 -1
  25. package/dist/layouts/booking/pages/ProductDetailPage.js +2 -1
  26. package/dist/layouts/booking/pages/ServicesPage.d.ts.map +1 -1
  27. package/dist/layouts/booking/pages/ServicesPage.js +4 -2
  28. package/dist/layouts/booking-agenda/pages/AboutPage.d.ts.map +1 -1
  29. package/dist/layouts/booking-agenda/pages/AboutPage.js +3 -1
  30. package/dist/layouts/booking-agenda/pages/CategoryPage.d.ts.map +1 -1
  31. package/dist/layouts/booking-agenda/pages/CategoryPage.js +3 -1
  32. package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts.map +1 -1
  33. package/dist/layouts/booking-agenda/pages/ProductDetailPage.js +2 -1
  34. package/dist/layouts/booking-agenda/pages/ServicesPage.d.ts.map +1 -1
  35. package/dist/layouts/booking-agenda/pages/ServicesPage.js +4 -2
  36. package/dist/layouts/clothing/components/ClothingHomePage.d.ts.map +1 -1
  37. package/dist/layouts/clothing/components/ClothingHomePage.js +5 -4
  38. package/dist/layouts/clothing/pages/AboutPage.d.ts.map +1 -1
  39. package/dist/layouts/clothing/pages/AboutPage.js +2 -1
  40. package/dist/layouts/clothing/pages/CategoriesPage.d.ts.map +1 -1
  41. package/dist/layouts/clothing/pages/CategoriesPage.js +3 -2
  42. package/dist/layouts/clothing/pages/CategoryPage.d.ts +3 -1
  43. package/dist/layouts/clothing/pages/CategoryPage.d.ts.map +1 -1
  44. package/dist/layouts/clothing/pages/CategoryPage.js +4 -3
  45. package/dist/layouts/clothing/pages/ProductDetailPage.d.ts.map +1 -1
  46. package/dist/layouts/clothing/pages/ProductDetailPage.js +3 -2
  47. package/dist/layouts/clothing/pages/ProductsPage.d.ts.map +1 -1
  48. package/dist/layouts/clothing/pages/ProductsPage.js +53 -60
  49. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.d.ts.map +1 -1
  50. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.js +4 -3
  51. package/dist/layouts/clothing-minimal/pages/AboutPage.d.ts.map +1 -1
  52. package/dist/layouts/clothing-minimal/pages/AboutPage.js +2 -1
  53. package/dist/layouts/clothing-minimal/pages/CategoriesPage.d.ts.map +1 -1
  54. package/dist/layouts/clothing-minimal/pages/CategoriesPage.js +3 -2
  55. package/dist/layouts/clothing-minimal/pages/CategoryPage.d.ts +3 -1
  56. package/dist/layouts/clothing-minimal/pages/CategoryPage.d.ts.map +1 -1
  57. package/dist/layouts/clothing-minimal/pages/CategoryPage.js +4 -3
  58. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts.map +1 -1
  59. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.js +2 -1
  60. package/dist/layouts/clothing-minimal/pages/ProductsPage.d.ts.map +1 -1
  61. package/dist/layouts/clothing-minimal/pages/ProductsPage.js +53 -60
  62. package/dist/layouts/electronics/components/ElectronicsHomePage.d.ts.map +1 -1
  63. package/dist/layouts/electronics/components/ElectronicsHomePage.js +2 -1
  64. package/dist/layouts/electronics/components/ElectronicsProductsPage.d.ts.map +1 -1
  65. package/dist/layouts/electronics/components/ElectronicsProductsPage.js +45 -36
  66. package/dist/layouts/electronics/components/ElectronicsStoreFooter.d.ts.map +1 -1
  67. package/dist/layouts/electronics/components/ElectronicsStoreFooter.js +2 -1
  68. package/dist/layouts/electronics/pages/AboutPage.d.ts.map +1 -1
  69. package/dist/layouts/electronics/pages/AboutPage.js +3 -1
  70. package/dist/layouts/electronics/pages/CategoryPage.d.ts +3 -1
  71. package/dist/layouts/electronics/pages/CategoryPage.d.ts.map +1 -1
  72. package/dist/layouts/electronics/pages/CategoryPage.js +4 -3
  73. package/dist/layouts/electronics/pages/ProductDetailPage.d.ts.map +1 -1
  74. package/dist/layouts/electronics/pages/ProductDetailPage.js +2 -1
  75. package/dist/layouts/electronics/pages/ProductsPage.d.ts.map +1 -1
  76. package/dist/layouts/electronics/pages/ProductsPage.js +53 -60
  77. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.d.ts.map +1 -1
  78. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.js +2 -1
  79. package/dist/layouts/electronics-grid/pages/AboutPage.d.ts.map +1 -1
  80. package/dist/layouts/electronics-grid/pages/AboutPage.js +3 -1
  81. package/dist/layouts/electronics-grid/pages/CategoryPage.d.ts +3 -1
  82. package/dist/layouts/electronics-grid/pages/CategoryPage.d.ts.map +1 -1
  83. package/dist/layouts/electronics-grid/pages/CategoryPage.js +4 -3
  84. package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts.map +1 -1
  85. package/dist/layouts/electronics-grid/pages/ProductDetailPage.js +2 -1
  86. package/dist/layouts/electronics-grid/pages/ProductsPage.d.ts.map +1 -1
  87. package/dist/layouts/electronics-grid/pages/ProductsPage.js +53 -60
  88. package/dist/layouts/food/components/FoodHomePage.d.ts.map +1 -1
  89. package/dist/layouts/food/components/FoodHomePage.js +6 -4
  90. package/dist/layouts/food/pages/AboutPage.d.ts.map +1 -1
  91. package/dist/layouts/food/pages/AboutPage.js +2 -1
  92. package/dist/layouts/food/pages/CategoryPage.d.ts +3 -1
  93. package/dist/layouts/food/pages/CategoryPage.d.ts.map +1 -1
  94. package/dist/layouts/food/pages/CategoryPage.js +5 -3
  95. package/dist/layouts/food/pages/MenuPage.js +1 -1
  96. package/dist/layouts/food/pages/ProductDetailPage.d.ts.map +1 -1
  97. package/dist/layouts/food/pages/ProductDetailPage.js +2 -1
  98. package/dist/layouts/food/pages/ProductsPage.d.ts.map +1 -1
  99. package/dist/layouts/food/pages/ProductsPage.js +51 -54
  100. package/dist/layouts/food-modern/components/FoodHomePageModern.d.ts.map +1 -1
  101. package/dist/layouts/food-modern/components/FoodHomePageModern.js +4 -2
  102. package/dist/layouts/food-modern/pages/AboutPage.d.ts.map +1 -1
  103. package/dist/layouts/food-modern/pages/AboutPage.js +3 -1
  104. package/dist/layouts/food-modern/pages/CategoryPage.d.ts +3 -1
  105. package/dist/layouts/food-modern/pages/CategoryPage.d.ts.map +1 -1
  106. package/dist/layouts/food-modern/pages/CategoryPage.js +5 -3
  107. package/dist/layouts/food-modern/pages/MenuPage.js +1 -1
  108. package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts.map +1 -1
  109. package/dist/layouts/food-modern/pages/ProductDetailPage.js +2 -1
  110. package/dist/layouts/food-modern/pages/ProductsPage.d.ts.map +1 -1
  111. package/dist/layouts/food-modern/pages/ProductsPage.js +51 -54
  112. package/dist/layouts/motivational-speaker/components/MotivationalHomePage.d.ts.map +1 -1
  113. package/dist/layouts/motivational-speaker/components/MotivationalHomePage.js +4 -2
  114. package/dist/layouts/motivational-speaker/pages/AboutPage.d.ts.map +1 -1
  115. package/dist/layouts/motivational-speaker/pages/AboutPage.js +3 -1
  116. package/dist/layouts/motivational-speaker/pages/CategoryPage.d.ts +3 -1
  117. package/dist/layouts/motivational-speaker/pages/CategoryPage.d.ts.map +1 -1
  118. package/dist/layouts/motivational-speaker/pages/CategoryPage.js +6 -4
  119. package/dist/layouts/motivational-speaker/pages/ProductsPage.d.ts.map +1 -1
  120. package/dist/layouts/motivational-speaker/pages/ProductsPage.js +53 -60
  121. package/dist/layouts/motivational-speaker/pages/ServiceDetailPage.d.ts.map +1 -1
  122. package/dist/layouts/motivational-speaker/pages/ServiceDetailPage.js +2 -1
  123. package/dist/layouts/motivational-speaker/pages/ServicesPage.d.ts.map +1 -1
  124. package/dist/layouts/motivational-speaker/pages/ServicesPage.js +4 -2
  125. package/dist/layouts/motivational-speaker/pages/SubscriptionPage.d.ts.map +1 -1
  126. package/dist/layouts/motivational-speaker/pages/SubscriptionPage.js +3 -2
  127. package/dist/layouts/shared/components/StoreFooter.d.ts.map +1 -1
  128. package/dist/layouts/shared/components/StoreFooter.js +3 -13
  129. package/dist/layouts/shared/pages/PortfolioPage.d.ts.map +1 -1
  130. package/dist/layouts/shared/pages/PortfolioPage.js +2 -1
  131. package/dist/layouts/shared/pages/StoreMaintenanceScreen.d.ts +9 -0
  132. package/dist/layouts/shared/pages/StoreMaintenanceScreen.d.ts.map +1 -0
  133. package/dist/layouts/shared/pages/StoreMaintenanceScreen.js +10 -0
  134. package/dist/layouts/shared/pages/StoreOfflinePage.d.ts +19 -0
  135. package/dist/layouts/shared/pages/StoreOfflinePage.d.ts.map +1 -0
  136. package/dist/layouts/shared/pages/StoreOfflinePage.js +113 -0
  137. package/dist/layouts/shared/pages/WishlistPage.d.ts.map +1 -1
  138. package/dist/layouts/shared/pages/WishlistPage.js +11 -14
  139. package/dist/lib/content-selectors.js +3 -3
  140. package/dist/lib/layout-route-utils.d.ts +1 -0
  141. package/dist/lib/layout-route-utils.d.ts.map +1 -1
  142. package/dist/lib/layout-route-utils.js +1 -1
  143. package/dist/lib/services/product.service.d.ts +1 -0
  144. package/dist/lib/services/product.service.d.ts.map +1 -1
  145. package/dist/lib/store-context.d.ts +1 -0
  146. package/dist/lib/store-context.d.ts.map +1 -1
  147. package/dist/lib/store-context.js +1 -0
  148. package/dist/lib/utils/catalog-price-bounds.d.ts +2 -0
  149. package/dist/lib/utils/catalog-price-bounds.d.ts.map +1 -1
  150. package/dist/lib/utils/catalog-price-bounds.js +21 -0
  151. package/dist/lib/utils/filtered-product-query.d.ts +22 -0
  152. package/dist/lib/utils/filtered-product-query.d.ts.map +1 -0
  153. package/dist/lib/utils/filtered-product-query.js +57 -0
  154. package/dist/lib/utils/filtered-products-inflight.d.ts +3 -0
  155. package/dist/lib/utils/filtered-products-inflight.d.ts.map +1 -0
  156. package/dist/lib/utils/filtered-products-inflight.js +15 -0
  157. package/dist/lib/utils/url-helpers.d.ts.map +1 -1
  158. package/dist/lib/utils/url-helpers.js +2 -11
  159. package/dist/styles/index.css +33 -6
  160. package/package.json +2 -2
@@ -18,6 +18,7 @@ import { getGuestUserInfo, saveGuestUserInfo } from '../../../lib/guest-user.js'
18
18
  import { ProductCard } from '../../../components/ui/product-card.js';
19
19
  import Image from 'next/image';
20
20
  import { ImageWithFallback } from '../../../components/ui/image-with-fallback.js';
21
+ import { SafeRichHtml } from '../../../components/rich-text/SafeRichHtml.js';
21
22
  import { ButtonLoader } from '../../../components/ui/page-loader.js';
22
23
  import { extractImageUrls } from '../../../lib/store-config-utils.js';
23
24
  import { OutOfStockOverlay } from '../../../components/ui/out-of-stock-overlay.js';
@@ -509,5 +510,5 @@ export function ProductDetailPage({ storeConfig: initialConfig, productSlug }) {
509
510
  : 'bg-white text-gray-700 border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: variant.value }, variant.id));
510
511
  }) })] })), _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)
511
512
  ? "border-red-500 bg-red-50 text-red-500 hover:bg-red-100"
512
- : "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 })] }));
513
+ : "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(SafeRichHtml, { value: product.description, fallbackPlain: "", as: "div" }), _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 })] }));
513
514
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics/pages/ProductsPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAyB9D,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA2wBD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAMpD"}
1
+ {"version":3,"file":"ProductsPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics/pages/ProductsPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AA+B9D,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAkwBD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAMpD"}
@@ -13,14 +13,17 @@ import { useLoading } from '../../../lib/loading-context.js';
13
13
  import { useAnalytics } from '../../../hooks/use-analytics.js';
14
14
  import { ChevronDown, ChevronUp, Star, Check, Search, RotateCcw, SlidersHorizontal } from 'lucide-react';
15
15
  import { useSearchParams } from 'next/navigation';
16
- import { useState, useMemo, useEffect, useRef, Suspense } from 'react';
16
+ import { useState, useMemo, useEffect, Suspense } from 'react';
17
17
  import { useProductBrands } from '../../../hooks/use-product-brands.js';
18
+ import { useFilteredProductsFetch } from '../../../hooks/use-filtered-products-fetch.js';
18
19
  import { filterActiveProducts } from '../../../lib/utils/index.js';
19
20
  import { getAllCategoryIds, flattenCategoryTree, buildCategoryTree } from '../../../lib/utils/category-tree.js';
20
21
  import { getBannerImage, getLayoutText } from '../../../lib/utils/asset-helpers.js';
21
22
  import { shouldUseAPI } from '../../../lib/utils/demo-detection.js';
22
23
  import { useCatalogPriceRange } from '../../../hooks/use-catalog-price-range.js';
23
- import { isWithinActivePriceRange } from '../../../lib/utils/catalog-price-bounds.js';
24
+ import { getApiPriceFilterActive, isWithinActivePriceRange } from '../../../lib/utils/catalog-price-bounds.js';
25
+ import { buildFilteredProductQuery, getFilteredProductQueryKey, } from '../../../lib/utils/filtered-product-query.js';
26
+ import { transformProductToStoreProduct } from '../../../lib/store-config-utils.js';
24
27
  import { ProductPriceFilterSection } from '../../shared/components/ProductPriceFilterSection';
25
28
  function ProductsPageContent({ storeConfig: initialConfig }) {
26
29
  const { store, addToCart } = useStore();
@@ -63,7 +66,9 @@ function ProductsPageContent({ storeConfig: initialConfig }) {
63
66
  const [selectedBrands, setSelectedBrands] = useState([]);
64
67
  const [selectedCategories, setSelectedCategories] = useState([]);
65
68
  const storeCurrency = storeConfig.settings?.currency || 'NGN';
66
- const { priceRange, setPriceRange, catalogBounds, resetPriceRange, hasActivePriceFilter, } = useCatalogPriceRange(products);
69
+ const bootstrapProducts = useMemo(() => filterActiveProducts(storeConfig.products || []), [storeConfig.products]);
70
+ const priceCatalogItems = bootstrapProducts.length > 0 ? bootstrapProducts : products;
71
+ const { priceRange, setPriceRange, catalogBounds, resetPriceRange, hasActivePriceFilter, } = useCatalogPriceRange(priceCatalogItems);
67
72
  const [selectedCategoryFilter, setSelectedCategoryFilter] = useState(null);
68
73
  // Initialize filters from URL
69
74
  useEffect(() => {
@@ -181,64 +186,52 @@ function ProductsPageContent({ storeConfig: initialConfig }) {
181
186
  }
182
187
  return result;
183
188
  }, [products, selectedBrands, effectiveCategoryIds, priceRange, selectedCategoryFilter, minRating, showInStockOnly, sortBy, categories]);
184
- const productQuery = useMemo(() => {
185
- const categoryIds = new Set(effectiveCategoryIds);
186
- const selectedCategory = categories.find((category) => category.slug === selectedCategoryFilter);
187
- if (selectedCategory)
188
- getAllCategoryIds(selectedCategory).forEach((id) => categoryIds.add(id));
189
- return {
189
+ const hasApiPriceFilter = getApiPriceFilterActive(priceRange, bootstrapProducts);
190
+ const priceQueryMin = hasApiPriceFilter ? priceRange[0] : undefined;
191
+ const priceQueryMax = hasApiPriceFilter ? priceRange[1] : undefined;
192
+ const { productQueryParams, productQueryKey } = useMemo(() => {
193
+ const params = buildFilteredProductQuery({
190
194
  storeId: storeConfig.id,
191
- categoryIds: categoryIds.size ? Array.from(categoryIds).join(',') : undefined,
192
- brands: selectedBrands.length ? selectedBrands.join(',') : undefined,
193
- minPrice: priceRange[0] || undefined,
194
- maxPrice: priceRange[1] < catalogBounds.max ? priceRange[1] : undefined,
195
- rating: minRating || undefined,
196
- inStock: showInStockOnly || undefined,
195
+ categories,
196
+ effectiveCategoryIds,
197
+ selectedCategoryFilter,
198
+ selectedBrands,
199
+ priceRange,
200
+ hasActivePriceFilter: hasApiPriceFilter,
201
+ minRating,
202
+ showInStockOnly,
197
203
  sortBy,
204
+ });
205
+ return {
206
+ productQueryParams: params,
207
+ productQueryKey: getFilteredProductQueryKey(params),
198
208
  };
199
- }, [catalogBounds.max, categories, effectiveCategoryIds, minRating, priceRange, selectedBrands, selectedCategoryFilter, showInStockOnly, sortBy, storeConfig.id]);
200
- const skipBootstrapRefetch = useRef(true);
201
- useEffect(() => {
202
- let cancelled = false;
203
- const isDefaultQuery = !productQuery.categoryIds &&
204
- !productQuery.brands &&
205
- !productQuery.minPrice &&
206
- productQuery.maxPrice === undefined &&
207
- !productQuery.rating &&
208
- !productQuery.inStock &&
209
- productQuery.sortBy === 'featured';
210
- const fetchFilteredProducts = async () => {
211
- // Keep SSR bootstrap first paint; only refetch when filters/sort change.
212
- if (skipBootstrapRefetch.current && isDefaultQuery && products.length > 0) {
213
- skipBootstrapRefetch.current = false;
214
- setTotalProducts(storeConfig.productsTotal || products.length);
215
- return;
216
- }
217
- skipBootstrapRefetch.current = false;
218
- setIsLoadingProducts(true);
219
- try {
220
- const { productService } = await import('../../../lib/services/product.service.js');
221
- const { transformProductToStoreProduct } = await import('../../../lib/store-config-utils.js');
222
- const response = await productService.getProducts({ ...productQuery, page: 1, limit: 12 });
223
- if (cancelled)
224
- return;
225
- setProducts(response.data.map(transformProductToStoreProduct));
226
- setCurrentPage(1);
227
- setTotalProducts(response.meta.total);
228
- setVisibleProducts(12);
229
- }
230
- catch (error) {
231
- if (!cancelled)
232
- console.error('Failed to fetch products:', error);
233
- }
234
- finally {
235
- if (!cancelled)
236
- setIsLoadingProducts(false);
237
- }
238
- };
239
- fetchFilteredProducts();
240
- return () => { cancelled = true; };
241
- }, [productQuery]);
209
+ }, [
210
+ storeConfig.id,
211
+ categories,
212
+ effectiveCategoryIds,
213
+ selectedCategoryFilter,
214
+ selectedBrands,
215
+ hasApiPriceFilter,
216
+ priceQueryMin,
217
+ priceQueryMax,
218
+ minRating,
219
+ showInStockOnly,
220
+ sortBy,
221
+ ]);
222
+ useFilteredProductsFetch(productQueryParams, productQueryKey, {
223
+ bootstrapItemCount: bootstrapProducts.length,
224
+ bootstrapTotal: storeConfig.productsTotal,
225
+ mapResponse: (data) => data.map(transformProductToStoreProduct),
226
+ applyResults: (items, total) => {
227
+ setProducts(items);
228
+ setCurrentPage(1);
229
+ setTotalProducts(total);
230
+ setVisibleProducts(12);
231
+ },
232
+ setTotalProducts,
233
+ setLoading: setIsLoadingProducts,
234
+ });
242
235
  const displayedProducts = filteredAndSortedProducts.slice(0, visibleProducts);
243
236
  const hasMore = currentPage * 12 < totalProducts;
244
237
  const handleLoadMore = async () => {
@@ -249,7 +242,7 @@ function ProductsPageContent({ storeConfig: initialConfig }) {
249
242
  const { productService } = await import('../../../lib/services/product.service.js');
250
243
  const { transformProductToStoreProduct } = await import('../../../lib/store-config-utils.js');
251
244
  const nextPage = currentPage + 1;
252
- const response = await productService.getProducts({ ...productQuery, page: nextPage, limit: 12 });
245
+ const response = await productService.getProducts({ ...productQueryParams, page: nextPage, limit: 12 });
253
246
  setProducts((current) => [...current, ...response.data.map(transformProductToStoreProduct)]);
254
247
  setCurrentPage(nextPage);
255
248
  setTotalProducts(response.meta.total);
@@ -319,7 +312,7 @@ function ProductsPageContent({ storeConfig: initialConfig }) {
319
312
  const secondaryButtonText = hasSecondaryButtonFromConfig
320
313
  ? (categoryHeaderSecondaryButton && categoryHeaderSecondaryButton.trim() !== '' ? categoryHeaderSecondaryButton.trim() : null)
321
314
  : getLayoutText(storeConfig, 'sections.categories.viewAll', 'View Categories');
322
- return (_jsxs("div", { className: "min-h-screen bg-white font-sans text-slate-900", children: [_jsxs("div", { className: "relative overflow-hidden bg-white", children: [categoryHeaderImage && (_jsxs("div", { className: "absolute inset-0 z-0", children: [_jsx(ImageWithFallback, { src: categoryHeaderImage, alt: categoryHeaderTitle || storeConfig.name, className: "w-full h-full object-cover", skeletonAspectRatio: "16/9" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-black/60 via-black/40 to-black/60" })] })), !categoryHeaderImage && (_jsxs("div", { className: "absolute top-0 left-0 w-full h-full overflow-hidden z-0 pointer-events-none", children: [_jsx("div", { className: "absolute top-[-10%] right-[-5%] w-[500px] h-[500px] bg-gray-100 rounded-full mix-blend-multiply filter blur-3xl opacity-70 animate-pulse-slow" }), _jsx("div", { className: "absolute bottom-[-10%] left-[-10%] w-[400px] h-[400px] bg-gray-50 rounded-full mix-blend-multiply filter blur-3xl opacity-70 animate-pulse-slow", style: { animationDelay: '2s' } })] })), _jsx("div", { className: `container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 pt-12 pb-16 lg:pt-20 lg:pb-24 ${categoryHeaderImage ? 'min-h-[500px] flex items-center' : ''}`, children: _jsx("div", { className: "flex flex-col items-center w-full max-w-4xl mx-auto", children: _jsxs("div", { className: `w-full text-center lg:text-left animate-fade-in-up ${categoryHeaderImage ? 'text-white' : ''}`, children: [_jsx("div", { className: "flex justify-center lg:justify-start mb-6", children: _jsx("div", { className: categoryHeaderImage ? 'bg-white/10 backdrop-blur-md px-4 py-2 rounded-full border border-white/20' : '', children: _jsx(Breadcrumbs, { items: breadcrumbItems, variant: categoryHeaderImage ? 'light' : 'default' }) }) }), _jsxs("div", { className: `inline-flex items-center gap-2 px-3 py-1 rounded-full text-xs font-bold tracking-wider uppercase mb-6 ${categoryHeaderImage ? 'bg-white/20 backdrop-blur-md text-white border border-white/30' : 'bg-black/5 text-gray-900'}`, children: [_jsx("span", { className: `w-2 h-2 rounded-full animate-pulse ${categoryHeaderImage ? 'bg-white' : 'bg-black'}` }), getLayoutText(storeConfig, 'common.newArrivals', 'New Arrivals 2024')] }), _jsx("h1", { className: `text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight mb-6 leading-[1.1] ${categoryHeaderImage ? 'text-white' : 'text-gray-900'}`, children: categoryHeaderTitle || (_jsxs(_Fragment, { children: ["Explore The Collections of ", _jsx("br", {}), _jsx("span", { className: "text-transparent bg-clip-text bg-gradient-to-r from-gray-900 via-gray-700 to-gray-900", children: storeConfig.name })] })) }), _jsx("p", { className: `text-lg mb-8 leading-relaxed max-w-lg mx-auto lg:mx-0 ${categoryHeaderImage ? 'text-white/90' : 'text-gray-600'}`, children: getLayoutText(storeConfig, 'category_header:description', "Don't miss out on shopping our latest collection! curated for quality and style. Experience the perfect blend of modern aesthetics and premium craftsmanship.") }), _jsxs("div", { className: "flex flex-col sm:flex-row gap-4 justify-center lg:justify-start", children: [primaryButtonText && primaryButtonText.trim() !== '' && (_jsx(Button, { className: `h-12 px-8 rounded-full text-base font-medium shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 ${categoryHeaderImage ? 'bg-white text-gray-900 hover:bg-gray-100' : ''}`, onClick: () => {
315
+ return (_jsxs("div", { className: "min-h-screen bg-white font-sans text-slate-900", children: [_jsxs("div", { className: "relative overflow-hidden bg-white", children: [categoryHeaderImage && (_jsxs("div", { className: "absolute inset-0 z-0", children: [_jsx(ImageWithFallback, { src: categoryHeaderImage, alt: categoryHeaderTitle || storeConfig.name, className: "w-full h-full object-cover", skeletonAspectRatio: "16/9" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-black/60 via-black/40 to-black/60" })] })), !categoryHeaderImage && (_jsxs("div", { className: "absolute top-0 left-0 w-full h-full overflow-hidden z-0 pointer-events-none", children: [_jsx("div", { className: "absolute top-[-10%] right-[-5%] w-[500px] h-[500px] bg-gray-100 rounded-full mix-blend-multiply filter blur-3xl opacity-70 animate-pulse-slow" }), _jsx("div", { className: "absolute bottom-[-10%] left-[-10%] w-[400px] h-[400px] bg-gray-50 rounded-full mix-blend-multiply filter blur-3xl opacity-70 animate-pulse-slow", style: { animationDelay: '2s' } })] })), _jsx("div", { className: `container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 pt-12 pb-16 lg:pt-20 lg:pb-24 ${categoryHeaderImage ? 'min-h-[500px] flex items-center' : ''}`, children: _jsx("div", { className: "flex flex-col items-center w-full max-w-4xl mx-auto", children: _jsxs("div", { className: `w-full text-center lg:text-left animate-fade-in-up ${categoryHeaderImage ? 'text-white' : ''}`, children: [_jsx("div", { className: "flex justify-center lg:justify-start mb-6", children: _jsx("div", { className: categoryHeaderImage ? 'bg-white/10 backdrop-blur-md px-4 py-2 rounded-full border border-white/20' : '', children: _jsx(Breadcrumbs, { items: breadcrumbItems, variant: categoryHeaderImage ? 'light' : 'default' }) }) }), _jsx("h1", { className: `text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight mb-6 leading-[1.1] ${categoryHeaderImage ? 'text-white' : 'text-gray-900'}`, children: categoryHeaderTitle || (_jsxs(_Fragment, { children: ["Explore The Collections of ", _jsx("br", {}), _jsx("span", { className: "text-transparent bg-clip-text bg-gradient-to-r from-gray-900 via-gray-700 to-gray-900", children: storeConfig.name })] })) }), _jsx("p", { className: `text-lg mb-8 leading-relaxed max-w-lg mx-auto lg:mx-0 ${categoryHeaderImage ? 'text-white/90' : 'text-gray-600'}`, children: getLayoutText(storeConfig, 'category_header:description', "Don't miss out on shopping our latest collection! curated for quality and style. Experience the perfect blend of modern aesthetics and premium craftsmanship.") }), _jsxs("div", { className: "flex flex-col sm:flex-row gap-4 justify-center lg:justify-start", children: [primaryButtonText && primaryButtonText.trim() !== '' && (_jsx(Button, { className: `h-12 px-8 rounded-full text-base font-medium shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 ${categoryHeaderImage ? 'bg-white text-gray-900 hover:bg-gray-100' : ''}`, onClick: () => {
323
316
  const element = document.getElementById('product-grid');
324
317
  element?.scrollIntoView({ behavior: 'smooth' });
325
318
  }, children: primaryButtonText })), secondaryButtonText && secondaryButtonText.trim() !== '' && (_jsx(Button, { className: `h-12 px-8 rounded-full text-base font-medium shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 ${categoryHeaderImage ? 'bg-white/10 backdrop-blur-md text-white border border-white/30 hover:bg-white/20' : 'bg-gray-100 text-gray-900 hover:bg-gray-200 border border-gray-200'}`, onClick: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ElectronicsHomePageGrid.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/components/ElectronicsHomePageGrid.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAA+B,MAAM,mBAAmB,CAAC;AAsB7E,UAAU,4BAA4B;IACnC,WAAW,EAAE,WAAW,CAAC;CAC3B;AA+ED,wBAAgB,uBAAuB,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,4BAA4B,+BAshBnG"}
1
+ {"version":3,"file":"ElectronicsHomePageGrid.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/components/ElectronicsHomePageGrid.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAA+B,MAAM,mBAAmB,CAAC;AAuB7E,UAAU,4BAA4B;IACnC,WAAW,EAAE,WAAW,CAAC;CAC3B;AA+ED,wBAAgB,uBAAuB,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,4BAA4B,+BAwhBnG"}
@@ -16,6 +16,7 @@ import { formatCurrency, cn, filterActiveProducts } from '../../../lib/utils/ind
16
16
  import { getLayoutText, getBannerImage, getLogoUrl } from '../../../lib/utils/asset-helpers.js';
17
17
  import { toStoreHref } from '../../../lib/utils/url-helpers.js';
18
18
  import { StoreLogo } from '../../../components/ui/store-logos.js';
19
+ import { RichTextExcerpt } from '../../../components/rich-text/RichTextExcerpt.js';
19
20
  import { PromoBanner } from '../../shared/components/PromoBanner';
20
21
  import { ElectronicsGridProductCard } from './ElectronicsGridProductCard';
21
22
  import { productService } from '../../../lib/services/product.service.js';
@@ -140,7 +141,7 @@ export function ElectronicsHomePageGrid({ storeConfig: initialConfig }) {
140
141
  return (_jsxs("div", { "data-section": "marketing", className: "mb-8 rounded-lg bg-white text-gray-900 py-12 px-6 flex items-center justify-between relative overflow-hidden min-h-[200px]", children: [_jsxs("div", { className: "absolute inset-0 z-0", children: [_jsx(Image, { src: bannerImage, alt: bannerTitle, fill: true, className: "object-cover", unoptimized: true }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-black/70 via-black/50 to-black/40" })] }), _jsxs("div", { className: "relative z-10 max-w-2xl", children: [_jsx("h2", { className: "text-4xl font-light mb-4 text-white tracking-tight", children: bannerTitle }), _jsx("p", { className: "text-gray-200 text-lg mb-8 leading-relaxed font-light", children: bannerSubtitle }), _jsx(Link, { href: bannerButtonLink, children: _jsx(Button, { size: "sm", className: "bg-white hover:bg-gray-100 text-gray-900 font-normal border-none transition-colors px-6 py-2.5 text-sm shadow-lg", children: bannerButtonText }) })] })] }));
141
142
  })(), _jsxs("div", { className: "bg-white py-4 mb-6 flex flex-wrap items-center gap-4 justify-between border-b border-gray-100", children: [_jsxs("div", { className: "flex items-center gap-6", children: [_jsxs("span", { className: "text-sm font-normal text-gray-600", children: [filteredProducts.length, " Items"] }), _jsx("div", { className: "h-4 w-px bg-gray-200" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-gray-500 font-normal", children: "Sort:" }), _jsxs("select", { className: "text-sm border-none bg-transparent font-normal text-gray-900 focus:ring-0 cursor-pointer p-0 pr-6 appearance-none", children: [_jsx("option", { children: "Best Match" }), _jsx("option", { children: "Price Low-High" }), _jsx("option", { children: "Price High-Low" }), _jsx("option", { children: "Highest Rated" })] })] })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs(Button, { variant: "ghost", size: "sm", className: "lg:hidden flex items-center gap-2 text-gray-600 hover:text-gray-900", onClick: () => setIsFilterOpen(true), children: [_jsx(Filter, { className: "h-4 w-4" }), " Filters"] }) })] }), _jsx(Sheet, { isOpen: isFilterOpen, onClose: () => setIsFilterOpen(false), title: "Filters", side: "left", children: _jsx(ElectronicsFilterContent, { categories: categories, storeSlug: storeConfig.slug }) }), _jsx("div", { "data-section": "products", className: "grid gap-4 sm:gap-6 lg:gap-8 grid-cols-2 sm:grid-cols-2 lg:grid-cols-3", children: filteredProducts.slice(0, visibleCount).map((product, index) => (
142
143
  // Grid View Card - High Density Info
143
- _jsx(ElectronicsGridProductCard, { product: product, storeSlug: storeConfig.slug, onAddToCart: handleAddToCart, index: index }, product.id))) }), catalogPage * LOAD_MORE_INCREMENT < catalogTotal && (_jsx("div", { className: "mt-16 flex justify-center border-t border-gray-100 pt-12", children: _jsx(Button, { variant: "outline", onClick: loadMoreProducts, disabled: isLoadingCatalog, className: "min-w-[200px] border-gray-300 text-gray-700 hover:bg-gray-50 hover:text-gray-900 font-normal transition-colors", children: isLoadingCatalog ? 'Loading...' : 'Load More Products' }) }))] })] })] }), _jsx("footer", { "data-section": "footer", className: "bg-white border-t border-gray-100 pt-16 pb-12 mt-20", children: _jsxs("div", { className: "container mx-auto px-6", children: [_jsxs("div", { className: "grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-8 mb-12", children: [_jsxs("div", { className: "lg:col-span-1", children: [_jsx("div", { className: "mb-6", children: _jsx("span", { className: "text-lg font-medium text-gray-900", children: storeConfig.name }) }), _jsx("p", { className: "text-sm text-gray-500 leading-relaxed mb-6 font-light", children: storeConfig.description || "Nigeria's premier destination for authentic Apple products. Authorized reseller with genuine warranty and exceptional service." }), _jsxs("div", { className: "flex gap-2", children: [_jsx("div", { className: "w-8 h-8 bg-gray-100 rounded flex items-center justify-center text-gray-400", children: _jsx(Smartphone, { className: "h-4 w-4" }) }), _jsx("div", { className: "w-8 h-8 bg-gray-100 rounded flex items-center justify-center text-gray-400", children: _jsx(Tag, { className: "h-4 w-4" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Shop" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/products`, className: "hover:text-gray-900 transition-colors", children: "All Products" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/categories`, className: "hover:text-gray-900 transition-colors", children: "Categories" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Support" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/help-center`, className: "hover:text-gray-900 transition-colors", children: "Help Center" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/shipping-returns`, className: "hover:text-gray-900 transition-colors", children: "Shipping & Returns" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/track-order`, className: "hover:text-gray-900 transition-colors", children: "Track Order" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Account" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/account`, className: "hover:text-gray-900 transition-colors", children: "My Account" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/track-order`, className: "hover:text-gray-900 transition-colors", children: "Track Order" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Stay Connected" }), _jsxs("form", { onSubmit: async (e) => {
144
+ _jsx(ElectronicsGridProductCard, { product: product, storeSlug: storeConfig.slug, onAddToCart: handleAddToCart, index: index }, product.id))) }), catalogPage * LOAD_MORE_INCREMENT < catalogTotal && (_jsx("div", { className: "mt-16 flex justify-center border-t border-gray-100 pt-12", children: _jsx(Button, { variant: "outline", onClick: loadMoreProducts, disabled: isLoadingCatalog, className: "min-w-[200px] border-gray-300 text-gray-700 hover:bg-gray-50 hover:text-gray-900 font-normal transition-colors", children: isLoadingCatalog ? 'Loading...' : 'Load More Products' }) }))] })] })] }), _jsx("footer", { "data-section": "footer", className: "bg-white border-t border-gray-100 pt-16 pb-12 mt-20", children: _jsxs("div", { className: "container mx-auto px-6", children: [_jsxs("div", { className: "grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-8 mb-12", children: [_jsxs("div", { className: "lg:col-span-1", children: [_jsx("div", { className: "mb-6", children: _jsx("span", { className: "text-lg font-medium text-gray-900", children: storeConfig.name }) }), _jsx(RichTextExcerpt, { value: storeConfig.description || "Nigeria's premier destination for authentic Apple products. Authorized reseller with genuine warranty and exceptional service.", as: "p", className: "text-sm text-gray-500 leading-relaxed mb-6 font-light" }), _jsxs("div", { className: "flex gap-2", children: [_jsx("div", { className: "w-8 h-8 bg-gray-100 rounded flex items-center justify-center text-gray-400", children: _jsx(Smartphone, { className: "h-4 w-4" }) }), _jsx("div", { className: "w-8 h-8 bg-gray-100 rounded flex items-center justify-center text-gray-400", children: _jsx(Tag, { className: "h-4 w-4" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Shop" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/products`, className: "hover:text-gray-900 transition-colors", children: "All Products" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/categories`, className: "hover:text-gray-900 transition-colors", children: "Categories" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Support" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/help-center`, className: "hover:text-gray-900 transition-colors", children: "Help Center" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/shipping-returns`, className: "hover:text-gray-900 transition-colors", children: "Shipping & Returns" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/track-order`, className: "hover:text-gray-900 transition-colors", children: "Track Order" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Account" }), _jsxs("ul", { className: "space-y-3 text-sm text-gray-500", children: [_jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/account`, className: "hover:text-gray-900 transition-colors", children: "My Account" }) }), _jsx("li", { children: _jsx(Link, { href: `/${storeConfig.slug}/track-order`, className: "hover:text-gray-900 transition-colors", children: "Track Order" }) })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900 text-sm mb-4", children: "Stay Connected" }), _jsxs("form", { onSubmit: async (e) => {
144
145
  e.preventDefault();
145
146
  const form = e.target;
146
147
  const emailInput = form.querySelector('input[type="email"]');
@@ -1 +1 @@
1
- {"version":3,"file":"AboutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/AboutPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,UAAU,cAAc;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,cAAc,+BA2OvE"}
1
+ {"version":3,"file":"AboutPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/AboutPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAShD,UAAU,cAAc;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,cAAc,+BA6OvE"}
@@ -5,6 +5,8 @@ import { Button } from '../../../components/ui/button.js';
5
5
  import { DotPattern } from '../../../components/ui/background-patterns.js';
6
6
  import { useStore } from '../../../lib/store-context.js';
7
7
  import Image from 'next/image';
8
+ import { SafeRichHtml } from '../../../components/rich-text/SafeRichHtml.js';
9
+ import { RichTextExcerpt } from '../../../components/rich-text/RichTextExcerpt.js';
8
10
  export function AboutPage({ storeConfig: initialConfig }) {
9
11
  const { store } = useStore();
10
12
  const storeConfig = store || initialConfig;
@@ -39,7 +41,7 @@ export function AboutPage({ storeConfig: initialConfig }) {
39
41
  description: "Commitment to reduced carbon footprint and energy-efficient tech."
40
42
  }
41
43
  ];
42
- return (_jsxs("div", { className: "min-h-screen bg-white pb-20 overflow-hidden", children: [_jsxs("section", { "data-section": "hero", className: "relative h-[60vh] min-h-[500px] w-full overflow-hidden", children: [_jsxs("div", { className: "absolute inset-0", children: [_jsx(Image, { src: heroImage, alt: "About Us", fill: true, className: "w-full h-full object-cover transform scale-105 animate-pulse-slow" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-black/80 via-black/50 to-transparent" })] }), _jsx("div", { className: "absolute inset-0 flex items-center", children: _jsx("div", { className: "container mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl animate-fade-in-up", children: [_jsxs("div", { className: "inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-md border border-white/20 text-white text-sm font-medium mb-6", children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-white animate-pulse" }), "Est. 2024"] }), _jsx("h1", { className: "text-5xl md:text-7xl font-bold text-white mb-6 tracking-tight leading-tight", children: pageTitle }), _jsx("p", { className: "text-xl md:text-2xl text-gray-200 max-w-2xl leading-relaxed font-light", children: missionStatement || storeConfig.description })] }) }) })] }), _jsxs("section", { "data-section": "story", className: "py-24 px-4 sm:px-6 lg:px-8 relative", children: [_jsx("div", { className: "absolute top-0 right-0 -mt-24 -mr-24 w-96 h-96 bg-gray-50 rounded-full blur-3xl -z-10" }), _jsx("div", { className: "container mx-auto max-w-7xl", children: _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "relative", children: [galleryImages && galleryImages.length > 0 ? (_jsx("div", { className: "grid grid-cols-2 gap-4", children: galleryImages.slice(0, 4).map((img, i) => (_jsx("div", { className: `relative overflow-hidden rounded-2xl shadow-lg ${i === 0 ? 'col-span-2 aspect-[16/9]' : 'aspect-square'}`, children: _jsx(Image, { src: img.image, alt: img.caption || "Gallery Image", fill: true, className: "w-full h-full object-cover hover:scale-110 transition-transform duration-500" }) }, i))) })) : (_jsxs("div", { className: "relative aspect-[4/5] rounded-[2rem] overflow-hidden shadow-2xl", children: [_jsx(Image, { src: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?q=80&w=2071&auto=format&fit=crop", alt: "Our Team", fill: true, className: "w-full h-full object-cover" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-60" }), _jsxs("div", { className: "absolute bottom-8 left-8 text-white", children: [_jsx("p", { className: "font-bold text-lg", children: "The Dream Team" }), _jsx("p", { className: "text-white/80 text-sm", children: "Working together to serve you better" })] })] })), _jsx("div", { className: "absolute -bottom-6 -right-6 w-24 h-24 bg-white rounded-2xl shadow-xl flex items-center justify-center p-4 animate-bounce duration-[3000ms]", children: _jsx(Heart, { className: "w-10 h-10", style: { color: primaryColor, fill: primaryColor } }) })] }), _jsxs("div", { className: "space-y-10", children: [_jsxs("div", { children: [_jsx("span", { className: "text-sm font-bold uppercase tracking-widest mb-3 block", style: { color: primaryColor }, children: "Who We Are" }), _jsx("h2", { className: "text-4xl md:text-5xl font-black text-gray-900 mb-6 tracking-tight", children: "Our Journey" }), _jsxs("div", { className: "prose prose-lg text-gray-600 leading-relaxed space-y-6", children: [pageContent?.split('\n').map((paragraph, idx) => (_jsx("p", { children: paragraph }, idx))), !pageContent && (_jsxs(_Fragment, { children: [_jsxs("p", { children: ["Founded with a bold vision to redefine excellence in the ", _jsx("span", { className: "font-semibold text-gray-900", children: storeConfig.type }), " industry, ", storeConfig.name, " has grown from a small passion project into a beloved brand. We believe in the power of quality, innovation, and community."] }), _jsx("p", { children: "Every day, we strive to bring you the best products, curated with care and delivered with a smile. Our team is dedicated to ensuring that your experience with us is nothing short of exceptional." })] }))] })] }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-8", children: values.map((item, idx) => (_jsxs("div", { className: "flex gap-4 group", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "w-14 h-14 rounded-2xl flex items-center justify-center transition-colors group-hover:bg-gray-100", style: { backgroundColor: `${primaryColor}10` }, children: _jsx(item.icon, { className: "h-7 w-7 transition-transform group-hover:scale-110", style: { color: primaryColor } }) }) }), _jsxs("div", { children: [_jsx("h4", { className: "font-bold text-gray-900 mb-2 text-lg", children: item.title }), _jsx("p", { className: "text-gray-600 text-sm leading-relaxed", children: item.description })] })] }, idx))) })] })] }) })] }), _jsxs("section", { "data-section": "stats", className: "py-20 relative overflow-hidden", children: [_jsx("div", { className: "absolute inset-0 opacity-10", children: _jsx(DotPattern, { color: primaryColor, cx: 2, cy: 2, cr: 2, width: 30, height: 30 }) }), _jsx("div", { className: "absolute inset-0", style: { backgroundColor: `${secondaryColor}15` } }), _jsx("div", { className: "container mx-auto px-4 relative z-10", children: _jsx("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12", children: [
44
+ return (_jsxs("div", { className: "min-h-screen bg-white pb-20 overflow-hidden", children: [_jsxs("section", { "data-section": "hero", className: "relative h-[60vh] min-h-[500px] w-full overflow-hidden", children: [_jsxs("div", { className: "absolute inset-0", children: [_jsx(Image, { src: heroImage, alt: "About Us", fill: true, className: "w-full h-full object-cover transform scale-105 animate-pulse-slow" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-black/80 via-black/50 to-transparent" })] }), _jsx("div", { className: "absolute inset-0 flex items-center", children: _jsx("div", { className: "container mx-auto px-4 sm:px-6 lg:px-8", children: _jsxs("div", { className: "max-w-3xl animate-fade-in-up", children: [_jsxs("div", { className: "inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-md border border-white/20 text-white text-sm font-medium mb-6", children: [_jsx("span", { className: "w-2 h-2 rounded-full bg-white animate-pulse" }), "Est. 2024"] }), _jsx("h1", { className: "text-5xl md:text-7xl font-bold text-white mb-6 tracking-tight leading-tight", children: pageTitle }), _jsx(SafeRichHtml, { value: missionStatement || storeConfig.description, as: "div", className: "text-xl md:text-2xl text-gray-200 max-w-2xl leading-relaxed font-light [&_p]:mb-0" })] }) }) })] }), _jsxs("section", { "data-section": "story", className: "py-24 px-4 sm:px-6 lg:px-8 relative", children: [_jsx("div", { className: "absolute top-0 right-0 -mt-24 -mr-24 w-96 h-96 bg-gray-50 rounded-full blur-3xl -z-10" }), _jsx("div", { className: "container mx-auto max-w-7xl", children: _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "relative", children: [galleryImages && galleryImages.length > 0 ? (_jsx("div", { className: "grid grid-cols-2 gap-4", children: galleryImages.slice(0, 4).map((img, i) => (_jsx("div", { className: `relative overflow-hidden rounded-2xl shadow-lg ${i === 0 ? 'col-span-2 aspect-[16/9]' : 'aspect-square'}`, children: _jsx(Image, { src: img.image, alt: img.caption || "Gallery Image", fill: true, className: "w-full h-full object-cover hover:scale-110 transition-transform duration-500" }) }, i))) })) : (_jsxs("div", { className: "relative aspect-[4/5] rounded-[2rem] overflow-hidden shadow-2xl", children: [_jsx(Image, { src: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?q=80&w=2071&auto=format&fit=crop", alt: "Our Team", fill: true, className: "w-full h-full object-cover" }), _jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-60" }), _jsxs("div", { className: "absolute bottom-8 left-8 text-white", children: [_jsx("p", { className: "font-bold text-lg", children: "The Dream Team" }), _jsx("p", { className: "text-white/80 text-sm", children: "Working together to serve you better" })] })] })), _jsx("div", { className: "absolute -bottom-6 -right-6 w-24 h-24 bg-white rounded-2xl shadow-xl flex items-center justify-center p-4 animate-bounce duration-[3000ms]", children: _jsx(Heart, { className: "w-10 h-10", style: { color: primaryColor, fill: primaryColor } }) })] }), _jsxs("div", { className: "space-y-10", children: [_jsxs("div", { children: [_jsx("span", { className: "text-sm font-bold uppercase tracking-widest mb-3 block", style: { color: primaryColor }, children: "Who We Are" }), _jsx("h2", { className: "text-4xl md:text-5xl font-black text-gray-900 mb-6 tracking-tight", children: "Our Journey" }), _jsxs("div", { className: "prose prose-lg text-gray-600 leading-relaxed space-y-6", children: [pageContent?.split('\n').map((paragraph, idx) => (_jsx("p", { children: paragraph }, idx))), !pageContent && (_jsxs(_Fragment, { children: [_jsxs("p", { children: ["Founded with a bold vision to redefine excellence in the ", _jsx("span", { className: "font-semibold text-gray-900", children: storeConfig.type }), " industry, ", storeConfig.name, " has grown from a small passion project into a beloved brand. We believe in the power of quality, innovation, and community."] }), _jsx("p", { children: "Every day, we strive to bring you the best products, curated with care and delivered with a smile. Our team is dedicated to ensuring that your experience with us is nothing short of exceptional." })] }))] })] }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-8", children: values.map((item, idx) => (_jsxs("div", { className: "flex gap-4 group", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "w-14 h-14 rounded-2xl flex items-center justify-center transition-colors group-hover:bg-gray-100", style: { backgroundColor: `${primaryColor}10` }, children: _jsx(item.icon, { className: "h-7 w-7 transition-transform group-hover:scale-110", style: { color: primaryColor } }) }) }), _jsxs("div", { children: [_jsx("h4", { className: "font-bold text-gray-900 mb-2 text-lg", children: item.title }), _jsx(RichTextExcerpt, { value: item.description, as: "p", className: "text-gray-600 text-sm leading-relaxed" })] })] }, idx))) })] })] }) })] }), _jsxs("section", { "data-section": "stats", className: "py-20 relative overflow-hidden", children: [_jsx("div", { className: "absolute inset-0 opacity-10", children: _jsx(DotPattern, { color: primaryColor, cx: 2, cy: 2, cr: 2, width: 30, height: 30 }) }), _jsx("div", { className: "absolute inset-0", style: { backgroundColor: `${secondaryColor}15` } }), _jsx("div", { className: "container mx-auto px-4 relative z-10", children: _jsx("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12", children: [
43
45
  { label: "Global Users", value: "100k+" },
44
46
  { label: "Gadgets", value: storeConfig.products?.length ? `${storeConfig.products.length * 15}+` : "150+" },
45
47
  { label: "Tech Awards", value: "25+" },
@@ -1,8 +1,10 @@
1
+ import { type CategoryProductsSeed } from '../../../hooks/use-category-products.js';
1
2
  import { StoreConfig } from '../../../lib/store-types.js';
2
3
  interface CategoryPageProps {
3
4
  storeConfig: StoreConfig;
4
5
  categorySlug: string;
6
+ categoryProductsSeed?: CategoryProductsSeed;
5
7
  }
6
- export declare function CategoryPage({ storeConfig, categorySlug }: CategoryPageProps): import("react").JSX.Element;
8
+ export declare function CategoryPage({ storeConfig, categorySlug, categoryProductsSeed }: CategoryPageProps): import("react").JSX.Element;
7
9
  export {};
8
10
  //# sourceMappingURL=CategoryPage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CategoryPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/CategoryPage.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAA8B,MAAM,mBAAmB,CAAC;AAc5E,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,iBAAiB,+BAsH5E"}
1
+ {"version":3,"file":"CategoryPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/CategoryPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE/F,OAAO,EAAE,WAAW,EAA8B,MAAM,mBAAmB,CAAC;AAe5E,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,wBAAgB,YAAY,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,oBAAoB,EAAE,EAAE,iBAAiB,+BAwHlG"}
@@ -10,10 +10,11 @@ import { useToast } from '../../../components/ui/toast.js';
10
10
  import { useAnalytics } from '../../../hooks/use-analytics.js';
11
11
  import { useEffect } from 'react';
12
12
  import { ProductCard } from '../../../components/ui/product-card.js';
13
- export function CategoryPage({ storeConfig, categorySlug }) {
13
+ import { CategoryDescription } from '../../../components/rich-text/CategoryDescription.js';
14
+ export function CategoryPage({ storeConfig, categorySlug, categoryProductsSeed }) {
14
15
  const categories = storeConfig.categories || [];
15
16
  const category = categories.find(c => c.slug === categorySlug);
16
- const { products, isLoading, hasMore, loadMore } = useCategoryProducts(storeConfig.id, category?.id);
17
+ const { products, isLoading, hasMore, loadMore } = useCategoryProducts(storeConfig.id, category?.id, categoryProductsSeed);
17
18
  const { addToCart } = useStore();
18
19
  const { addToast } = useToast();
19
20
  const { trackEvent } = useAnalytics();
@@ -45,5 +46,5 @@ export function CategoryPage({ storeConfig, categorySlug }) {
45
46
  const isDarkTheme = storeConfig.type === 'food-modern' || storeConfig.branding.theme === 'dark';
46
47
  const bgColor = isDarkTheme ? 'bg-[#0F0F0F]' : 'bg-gray-50';
47
48
  const textColor = isDarkTheme ? 'text-white' : 'text-gray-900';
48
- return (_jsxs("div", { className: "min-h-screen bg-gray-50 text-gray-900 transition-colors duration-300", children: [_jsxs("div", { className: "relative h-[40vh] overflow-hidden", children: [_jsx(ImageWithFallback, { src: category.image, alt: category.name, className: "w-full h-full object-cover", skeletonAspectRatio: "16/9" }), _jsx("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-[2px]" }), _jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-center p-6 text-white", children: [_jsx("h1", { className: "text-5xl md:text-7xl font-bold tracking-tight mb-4", children: category.name }), category.description && (_jsx("p", { className: "text-lg md:text-xl max-w-2xl opacity-90 font-light", children: category.description }))] })] }), _jsxs("div", { className: "container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12", children: [_jsxs("div", { className: "flex flex-col md:flex-row justify-between items-center mb-10 gap-4", children: [_jsxs(Link, { href: `/${storeConfig.slug}/categories`, className: "inline-flex items-center text-sm font-medium text-gray-600 hover:text-gray-900", children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), "Back to All Categories"] }), _jsx("div", { className: "flex items-center gap-4", children: _jsxs(Button, { variant: "outline", className: "bg-white", children: [_jsx(Filter, { className: "h-4 w-4 mr-2" }), " Filter"] }) })] }), !hasItems ? (_jsxs("div", { className: "text-center py-20 border border-dashed border-gray-300 rounded-3xl", children: [_jsx("p", { className: "text-gray-500 text-lg", children: "No products found in this category." }), _jsx(Button, { className: "mt-4", onClick: () => window.history.back(), children: "Go Back" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8", children: products.map((product) => (_jsx(ProductCard, { product: product, storeSlug: storeConfig.slug, onAddToCart: handleAddToCart, onQuickView: handleQuickView }, product.id))) }), hasMore && (_jsx("div", { className: "mt-10 flex justify-center", children: _jsx(Button, { onClick: loadMore, disabled: isLoading, children: "Load more" }) }))] }))] })] }));
49
+ return (_jsxs("div", { className: "min-h-screen bg-gray-50 text-gray-900 transition-colors duration-300", children: [_jsxs("div", { className: "relative h-[40vh] overflow-hidden", children: [_jsx(ImageWithFallback, { src: category.image, alt: category.name, className: "w-full h-full object-cover", skeletonAspectRatio: "16/9" }), _jsx("div", { className: "absolute inset-0 bg-black/40 backdrop-blur-[2px]" }), _jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-center p-6 text-white", children: [_jsx("h1", { className: "text-5xl md:text-7xl font-bold tracking-tight mb-4", children: category.name }), _jsx(CategoryDescription, { description: category.description })] })] }), _jsxs("div", { className: "container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-12", children: [_jsxs("div", { className: "flex flex-col md:flex-row justify-between items-center mb-10 gap-4", children: [_jsxs(Link, { href: `/${storeConfig.slug}/categories`, className: "inline-flex items-center text-sm font-medium text-gray-600 hover:text-gray-900", children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), "Back to All Categories"] }), _jsx("div", { className: "flex items-center gap-4", children: _jsxs(Button, { variant: "outline", className: "bg-white", children: [_jsx(Filter, { className: "h-4 w-4 mr-2" }), " Filter"] }) })] }), !hasItems ? (_jsxs("div", { className: "text-center py-20 border border-dashed border-gray-300 rounded-3xl", children: [_jsx("p", { className: "text-gray-500 text-lg", children: "No products found in this category." }), _jsx(Button, { className: "mt-4", onClick: () => window.history.back(), children: "Go Back" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8", children: products.map((product) => (_jsx(ProductCard, { product: product, storeSlug: storeConfig.slug, onAddToCart: handleAddToCart, onQuickView: handleQuickView }, product.id))) }), hasMore && (_jsx("div", { className: "mt-10 flex justify-center", children: _jsx(Button, { onClick: loadMore, disabled: isLoading, children: "Load more" }) }))] }))] })] }));
49
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProductDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/ProductDetailPage.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAA8C,MAAM,mBAAmB,CAAC;AA4B5F,UAAU,sBAAsB;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAsHD,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,EAAE,sBAAsB,+BA2iCpG"}
1
+ {"version":3,"file":"ProductDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/ProductDetailPage.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAA8C,MAAM,mBAAmB,CAAC;AA6B5F,UAAU,sBAAsB;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAsHD,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,EAAE,sBAAsB,+BA2iCpG"}
@@ -18,6 +18,7 @@ import { getGuestUserInfo, saveGuestUserInfo } from '../../../lib/guest-user.js'
18
18
  import { ProductCard } from '../../../components/ui/product-card.js';
19
19
  import Image from 'next/image';
20
20
  import { ImageWithFallback } from '../../../components/ui/image-with-fallback.js';
21
+ import { SafeRichHtml } from '../../../components/rich-text/SafeRichHtml.js';
21
22
  import { ButtonLoader } from '../../../components/ui/page-loader.js';
22
23
  import { extractImageUrls } from '../../../lib/store-config-utils.js';
23
24
  import { OutOfStockOverlay } from '../../../components/ui/out-of-stock-overlay.js';
@@ -509,5 +510,5 @@ export function ProductDetailPage({ storeConfig: initialConfig, productSlug }) {
509
510
  : 'bg-white text-gray-700 border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: variant.value }, variant.id));
510
511
  }) })] })), _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)
511
512
  ? "border-red-500 bg-red-50 text-red-500 hover:bg-red-100"
512
- : "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 })] }));
513
+ : "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(SafeRichHtml, { value: product.description, fallbackPlain: "", as: "div" }), _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 })] }));
513
514
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/ProductsPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAyB9D,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAywBD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAMpD"}
1
+ {"version":3,"file":"ProductsPage.d.ts","sourceRoot":"","sources":["../../../../src/layouts/electronics-grid/pages/ProductsPage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AA+B9D,UAAU,iBAAiB;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAgwBD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAMpD"}