@mohasinac/appkit 2.7.27 → 2.7.31

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 (397) hide show
  1. package/dist/_internal/client/features/filters/filter-load-options.d.ts +29 -0
  2. package/dist/_internal/client/features/filters/filter-load-options.js +98 -0
  3. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
  4. package/dist/_internal/server/features/checkout/actions.js +42 -35
  5. package/dist/_internal/server/features/classified/adapters.d.ts +21 -0
  6. package/dist/_internal/server/features/classified/adapters.js +24 -0
  7. package/dist/_internal/server/features/classified/index.d.ts +3 -0
  8. package/dist/_internal/server/features/classified/index.js +3 -0
  9. package/dist/_internal/server/features/classified/metadata.d.ts +8 -0
  10. package/dist/_internal/server/features/classified/metadata.js +43 -0
  11. package/dist/_internal/server/features/classified/og.d.ts +30 -0
  12. package/dist/_internal/server/features/classified/og.js +76 -0
  13. package/dist/_internal/server/features/digital-code/adapters.d.ts +21 -0
  14. package/dist/_internal/server/features/digital-code/adapters.js +29 -0
  15. package/dist/_internal/server/features/digital-code/index.d.ts +3 -0
  16. package/dist/_internal/server/features/digital-code/index.js +3 -0
  17. package/dist/_internal/server/features/digital-code/metadata.d.ts +8 -0
  18. package/dist/_internal/server/features/digital-code/metadata.js +36 -0
  19. package/dist/_internal/server/features/digital-code/og.d.ts +27 -0
  20. package/dist/_internal/server/features/digital-code/og.js +77 -0
  21. package/dist/_internal/server/features/live/adapters.d.ts +21 -0
  22. package/dist/_internal/server/features/live/adapters.js +34 -0
  23. package/dist/_internal/server/features/live/index.d.ts +3 -0
  24. package/dist/_internal/server/features/live/index.js +3 -0
  25. package/dist/_internal/server/features/live/metadata.d.ts +8 -0
  26. package/dist/_internal/server/features/live/metadata.js +39 -0
  27. package/dist/_internal/server/features/live/og.d.ts +27 -0
  28. package/dist/_internal/server/features/live/og.js +72 -0
  29. package/dist/_internal/server/features/promotions/actions.js +4 -3
  30. package/dist/_internal/server/jobs/core/onOrderCreate.js +19 -16
  31. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +25 -22
  32. package/dist/_internal/server/jobs/core/onProductWrite.js +48 -58
  33. package/dist/_internal/shared/actions/action-registry.js +504 -9
  34. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  35. package/dist/_internal/shared/features/brands/schema.d.ts +5 -5
  36. package/dist/_internal/shared/features/cart/schema.d.ts +18 -18
  37. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
  38. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +38 -38
  39. package/dist/_internal/shared/features/events/schema.d.ts +8 -8
  40. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  41. package/dist/_internal/shared/features/products/schema.d.ts +42 -42
  42. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  43. package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
  44. package/dist/_internal/shared/media/limits.js +4 -3
  45. package/dist/client.d.ts +4 -0
  46. package/dist/client.js +2 -0
  47. package/dist/configs/next.js +4 -0
  48. package/dist/constants/api-endpoints.d.ts +6 -0
  49. package/dist/constants/api-endpoints.js +2 -0
  50. package/dist/constants/field-names.d.ts +1 -0
  51. package/dist/constants/field-names.js +1 -0
  52. package/dist/constants/table-keys.d.ts +6 -0
  53. package/dist/constants/table-keys.js +9 -0
  54. package/dist/core/hooks/useSyncManager.js +9 -8
  55. package/dist/features/about/components/FeesView.js +10 -7
  56. package/dist/features/about/components/HelpPageView.js +10 -1
  57. package/dist/features/about/components/HowAuctionsWorkView.js +10 -1
  58. package/dist/features/about/components/HowCheckoutWorksView.js +10 -1
  59. package/dist/features/about/components/HowOffersWorkView.js +10 -1
  60. package/dist/features/about/components/HowOrdersWorkView.js +10 -1
  61. package/dist/features/about/components/HowPayoutsWorkView.js +10 -1
  62. package/dist/features/about/components/HowPreOrdersWorkView.js +10 -1
  63. package/dist/features/about/components/HowReviewsWorkView.js +10 -1
  64. package/dist/features/about/components/PublicProfileView.js +46 -16
  65. package/dist/features/about/components/SecurityPrivacyView.js +7 -1
  66. package/dist/features/account/components/AddressesIndexListing.js +2 -2
  67. package/dist/features/account/components/NotificationBell.js +27 -16
  68. package/dist/features/account/components/NotificationPreferencesPanel.d.ts +9 -0
  69. package/dist/features/account/components/NotificationPreferencesPanel.js +91 -0
  70. package/dist/features/account/components/UserSidebar.js +4 -4
  71. package/dist/features/account/components/UserSupportView.js +16 -6
  72. package/dist/features/account/components/index.d.ts +2 -0
  73. package/dist/features/account/components/index.js +1 -0
  74. package/dist/features/account/schemas/index.d.ts +4 -4
  75. package/dist/features/account/types/index.d.ts +34 -0
  76. package/dist/features/admin/actions/admin-actions.js +4 -3
  77. package/dist/features/admin/actions/notification-actions.d.ts +24 -22
  78. package/dist/features/admin/actions/notification-actions.js +122 -22
  79. package/dist/features/admin/components/AdminAdEditorView.js +29 -15
  80. package/dist/features/admin/components/AdminAddressEditorView.d.ts +7 -0
  81. package/dist/features/admin/components/AdminAddressEditorView.js +117 -0
  82. package/dist/features/admin/components/AdminAdsView.js +22 -28
  83. package/dist/features/admin/components/AdminAllEventEntriesView.js +6 -1
  84. package/dist/features/admin/components/AdminBidsView.js +10 -3
  85. package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
  86. package/dist/features/admin/components/AdminBlogView.js +8 -3
  87. package/dist/features/admin/components/AdminBrandsView.js +7 -2
  88. package/dist/features/admin/components/AdminBundleEditorView.js +5 -2
  89. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  90. package/dist/features/admin/components/AdminCarouselView.js +13 -7
  91. package/dist/features/admin/components/AdminCategoriesView.js +8 -3
  92. package/dist/features/admin/components/AdminCategoryEditorView.js +12 -9
  93. package/dist/features/admin/components/AdminContactView.js +6 -1
  94. package/dist/features/admin/components/AdminCouponEditorView.js +8 -2
  95. package/dist/features/admin/components/AdminCouponsView.js +6 -1
  96. package/dist/features/admin/components/AdminEmployeeEditorView.js +12 -9
  97. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  98. package/dist/features/admin/components/AdminFaqsView.js +7 -2
  99. package/dist/features/admin/components/AdminFeatureFlagsView.js +58 -13
  100. package/dist/features/admin/components/AdminFeaturesView.js +4 -3
  101. package/dist/features/admin/components/AdminMediaView.js +9 -8
  102. package/dist/features/admin/components/AdminNavigationView.js +10 -17
  103. package/dist/features/admin/components/AdminNewsletterView.js +6 -1
  104. package/dist/features/admin/components/AdminNotificationsView.js +11 -3
  105. package/dist/features/admin/components/AdminOrdersView.js +6 -1
  106. package/dist/features/admin/components/AdminPayoutsView.js +10 -3
  107. package/dist/features/admin/components/AdminPrizeDrawsView.js +10 -3
  108. package/dist/features/admin/components/AdminProductEditorView.d.ts +3 -1
  109. package/dist/features/admin/components/AdminProductEditorView.js +12 -9
  110. package/dist/features/admin/components/AdminProductsView.js +18 -12
  111. package/dist/features/admin/components/AdminReturnRequestsView.js +5 -4
  112. package/dist/features/admin/components/AdminReviewsView.js +36 -26
  113. package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
  114. package/dist/features/admin/components/AdminScammersView.js +28 -26
  115. package/dist/features/admin/components/AdminSectionsView.js +112 -99
  116. package/dist/features/admin/components/AdminSessionsView.js +10 -3
  117. package/dist/features/admin/components/AdminSidebar.js +4 -4
  118. package/dist/features/admin/components/AdminSiteSettingsView.js +45 -4
  119. package/dist/features/admin/components/AdminStoresView.js +6 -1
  120. package/dist/features/admin/components/AdminSublistingCategoriesView.js +0 -1
  121. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  122. package/dist/features/admin/components/AdminSupportTicketsView.js +32 -34
  123. package/dist/features/admin/components/AdminTeamView.js +6 -1
  124. package/dist/features/admin/components/AdminUserEditorView.js +8 -15
  125. package/dist/features/admin/components/AdminUsersView.js +6 -1
  126. package/dist/features/admin/components/AdminViewCards.js +4 -3
  127. package/dist/features/admin/components/DashboardStats.js +2 -2
  128. package/dist/features/admin/components/DataTable.js +2 -2
  129. package/dist/features/admin/components/index.d.ts +2 -0
  130. package/dist/features/admin/components/index.js +1 -0
  131. package/dist/features/admin/components/sections/adminSectionsTypes.js +4 -3
  132. package/dist/features/admin/repository/chat.repository.js +8 -8
  133. package/dist/features/admin/repository/site-settings.repository.d.ts +1 -0
  134. package/dist/features/admin/repository/site-settings.repository.js +11 -9
  135. package/dist/features/admin/schemas/firestore.d.ts +38 -0
  136. package/dist/features/admin/schemas/firestore.js +15 -0
  137. package/dist/features/auctions/components/AuctionBidsTable.d.ts +13 -0
  138. package/dist/features/auctions/components/AuctionBidsTable.js +62 -0
  139. package/dist/features/auctions/components/AuctionDetailPageView.js +15 -21
  140. package/dist/features/auctions/components/AuctionFilters.d.ts +7 -1
  141. package/dist/features/auctions/components/AuctionFilters.js +3 -2
  142. package/dist/features/auctions/components/MarketplaceAuctionCard.js +18 -9
  143. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +3 -2
  144. package/dist/features/auctions/components/index.d.ts +2 -1
  145. package/dist/features/auctions/components/index.js +1 -1
  146. package/dist/features/auctions/schemas/index.d.ts +14 -14
  147. package/dist/features/auth/actions/realtime-token-actions.js +19 -4
  148. package/dist/features/auth/components/RegisterForm.js +8 -4
  149. package/dist/features/auth/consent-otp.d.ts +2 -0
  150. package/dist/features/auth/consent-otp.js +8 -0
  151. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  152. package/dist/features/auth/schemas/firestore.js +18 -25
  153. package/dist/features/auth/schemas/index.d.ts +2 -2
  154. package/dist/features/before-after/api/[id]/route.js +8 -6
  155. package/dist/features/before-after/schemas/index.d.ts +2 -2
  156. package/dist/features/blog/actions/blog-actions.d.ts +3 -3
  157. package/dist/features/blog/components/BlogIndexListing.js +21 -2
  158. package/dist/features/blog/components/BlogPostForm.js +11 -5
  159. package/dist/features/blog/components/BlogPostView.js +10 -2
  160. package/dist/features/blog/schemas/index.d.ts +18 -18
  161. package/dist/features/cart/components/CartDrawer.js +3 -2
  162. package/dist/features/cart/components/CartView.js +2 -1
  163. package/dist/features/cart/components/CheckoutView.js +2 -1
  164. package/dist/features/cart/repository/cart.repository.js +4 -3
  165. package/dist/features/cart/utils/pending-ops.d.ts +1 -1
  166. package/dist/features/categories/api/[id]/route.js +4 -3
  167. package/dist/features/categories/api/route.js +4 -3
  168. package/dist/features/categories/components/BrandDetailPageView.js +2 -2
  169. package/dist/features/categories/components/BrandDetailTabs.d.ts +5 -1
  170. package/dist/features/categories/components/BrandDetailTabs.js +30 -16
  171. package/dist/features/categories/components/BundleCollage.d.ts +8 -0
  172. package/dist/features/categories/components/BundleCollage.js +50 -0
  173. package/dist/features/categories/components/BundleDetailView.js +2 -10
  174. package/dist/features/categories/components/BundleItemsPicker.js +20 -13
  175. package/dist/features/categories/components/CategoriesIndexListing.js +28 -9
  176. package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
  177. package/dist/features/categories/components/CategoryDetailTabs.d.ts +5 -1
  178. package/dist/features/categories/components/CategoryDetailTabs.js +31 -16
  179. package/dist/features/categories/components/CategoryProductsListing.js +52 -13
  180. package/dist/features/categories/components/index.d.ts +2 -0
  181. package/dist/features/categories/components/index.js +1 -0
  182. package/dist/features/categories/schemas/index.d.ts +6 -6
  183. package/dist/features/checkout/actions/checkout-actions.js +4 -3
  184. package/dist/features/checkout/hooks/usePaymentCheckout.js +31 -22
  185. package/dist/features/classified/components/ClassifiedFilters.d.ts +12 -0
  186. package/dist/features/classified/components/ClassifiedFilters.js +20 -0
  187. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +4 -0
  188. package/dist/features/classified/components/ClassifiedIndexListing.js +110 -0
  189. package/dist/features/classified/components/ClassifiedListView.d.ts +6 -0
  190. package/dist/features/classified/components/ClassifiedListView.js +43 -0
  191. package/dist/features/classified/components/index.d.ts +6 -0
  192. package/dist/features/classified/components/index.js +3 -0
  193. package/dist/features/collections/api/[slug]/route.js +16 -12
  194. package/dist/features/collections/schemas/index.d.ts +5 -5
  195. package/dist/features/consultation/api/[id]/route.js +12 -9
  196. package/dist/features/consultation/components/ConsultationForm.js +3 -2
  197. package/dist/features/consultation/schemas/index.d.ts +6 -6
  198. package/dist/features/contact/email.js +77 -116
  199. package/dist/features/copilot/components/AdminCopilotView.js +12 -2
  200. package/dist/features/corporate/api/[id]/route.js +12 -9
  201. package/dist/features/corporate/components/CorporateInquiryForm.js +2 -1
  202. package/dist/features/digital-codes/components/DigitalCodeFilters.d.ts +12 -0
  203. package/dist/features/digital-codes/components/DigitalCodeFilters.js +17 -0
  204. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +4 -0
  205. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +107 -0
  206. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +6 -0
  207. package/dist/features/digital-codes/components/DigitalCodesListView.js +37 -0
  208. package/dist/features/digital-codes/components/index.d.ts +6 -0
  209. package/dist/features/digital-codes/components/index.js +3 -0
  210. package/dist/features/events/actions/event-actions.js +4 -3
  211. package/dist/features/events/components/AdminEventEditorView.js +3 -2
  212. package/dist/features/events/components/AdminEventsView.js +4 -2
  213. package/dist/features/events/components/EventPollWidget.js +5 -5
  214. package/dist/features/events/components/EventsIndexListing.js +2 -2
  215. package/dist/features/events/repository/event-entry.repository.d.ts +1 -0
  216. package/dist/features/events/repository/event-entry.repository.js +5 -0
  217. package/dist/features/events/schemas/index.d.ts +20 -20
  218. package/dist/features/faq/actions/faq-actions.d.ts +8 -8
  219. package/dist/features/faq/components/ContactCTA.js +3 -1
  220. package/dist/features/faq/components/FAQAccordion.js +1 -1
  221. package/dist/features/faq/schemas/index.d.ts +4 -4
  222. package/dist/features/filters/AsyncFacetSection.d.ts +18 -0
  223. package/dist/features/filters/AsyncFacetSection.js +65 -0
  224. package/dist/features/filters/index.d.ts +2 -0
  225. package/dist/features/filters/index.js +1 -0
  226. package/dist/features/forms/Checkbox.js +2 -2
  227. package/dist/features/forms/Input.js +2 -2
  228. package/dist/features/forms/Radio.js +5 -5
  229. package/dist/features/forms/Select.js +2 -2
  230. package/dist/features/forms/Slider.js +2 -2
  231. package/dist/features/forms/Textarea.js +2 -2
  232. package/dist/features/homepage/api/[id]/route.js +4 -3
  233. package/dist/features/homepage/api/sections/[id]/route.js +12 -9
  234. package/dist/features/homepage/components/AdSlot.js +2 -1
  235. package/dist/features/homepage/components/AdvertisementBanner.js +5 -3
  236. package/dist/features/homepage/components/BrandsSection.js +2 -2
  237. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  238. package/dist/features/homepage/components/CharacterHotspot.d.ts +2 -2
  239. package/dist/features/homepage/components/CharacterHotspot.js +119 -157
  240. package/dist/features/homepage/components/CharacterHotspotForm.js +25 -20
  241. package/dist/features/homepage/components/CustomCardsSection.js +8 -6
  242. package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
  243. package/dist/features/homepage/components/GoogleReviewsSection.js +3 -3
  244. package/dist/features/homepage/components/HeroBanner.js +5 -4
  245. package/dist/features/homepage/components/HeroCarousel.js +13 -26
  246. package/dist/features/homepage/components/HowItWorksSection.js +4 -2
  247. package/dist/features/homepage/components/SocialFeedSection.js +2 -2
  248. package/dist/features/homepage/components/SocialPostCard.js +3 -2
  249. package/dist/features/homepage/lib/social-feed-fetcher.js +6 -3
  250. package/dist/features/layout/AppLayoutShell.d.ts +8 -2
  251. package/dist/features/layout/AppLayoutShell.js +54 -78
  252. package/dist/features/layout/BottomActions.js +43 -48
  253. package/dist/features/live/components/LiveItemFilters.d.ts +12 -0
  254. package/dist/features/live/components/LiveItemFilters.js +24 -0
  255. package/dist/features/live/components/LiveItemsIndexListing.d.ts +4 -0
  256. package/dist/features/live/components/LiveItemsIndexListing.js +108 -0
  257. package/dist/features/live/components/LiveItemsListView.d.ts +6 -0
  258. package/dist/features/live/components/LiveItemsListView.js +43 -0
  259. package/dist/features/live/components/index.d.ts +6 -0
  260. package/dist/features/live/components/index.js +3 -0
  261. package/dist/features/media/MediaLightbox.js +8 -14
  262. package/dist/features/media/types/index.d.ts +2 -2
  263. package/dist/features/media/upload/CameraCapture.js +2 -2
  264. package/dist/features/media/upload/ImageUpload.js +4 -2
  265. package/dist/features/media/upload/MediaUploadField.js +24 -8
  266. package/dist/features/media/upload/MediaUploadList.js +1 -1
  267. package/dist/features/orders/actions/order-actions.js +4 -3
  268. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -1
  269. package/dist/features/orders/components/OrderFilters.js +12 -9
  270. package/dist/features/orders/schemas/index.d.ts +6 -6
  271. package/dist/features/pre-orders/api/[id]/route.js +12 -9
  272. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -4
  273. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +29 -22
  274. package/dist/features/pre-orders/components/PreOrderFilters.d.ts +7 -1
  275. package/dist/features/pre-orders/components/PreOrderFilters.js +3 -2
  276. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +17 -52
  277. package/dist/features/pre-orders/components/PreorderCard.d.ts +0 -9
  278. package/dist/features/pre-orders/components/PreorderCard.js +2 -13
  279. package/dist/features/pre-orders/components/index.d.ts +1 -1
  280. package/dist/features/pre-orders/components/index.js +1 -1
  281. package/dist/features/pre-orders/schemas/index.d.ts +10 -10
  282. package/dist/features/products/api/[id]/route.js +9 -7
  283. package/dist/features/products/api/route.js +1 -1
  284. package/dist/features/products/columns/productTableColumns.js +3 -3
  285. package/dist/features/products/components/AuctionsIndexListing.js +15 -51
  286. package/dist/features/products/components/BidHistory.js +2 -2
  287. package/dist/features/products/components/CompareOverlay.d.ts +2 -0
  288. package/dist/features/products/components/CompareOverlay.js +3 -2
  289. package/dist/features/products/components/MakeOfferButton.js +20 -14
  290. package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -1
  291. package/dist/features/products/components/PrizeDrawCollage.d.ts +1 -15
  292. package/dist/features/products/components/PrizeDrawCollage.js +54 -14
  293. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
  294. package/dist/features/products/components/PrizeDrawEntryActions.js +2 -1
  295. package/dist/features/products/components/PrizeDrawItemsEditor.js +9 -7
  296. package/dist/features/products/components/PrizeDrawsIndexListing.js +18 -51
  297. package/dist/features/products/components/PrizeRevealModal.js +24 -14
  298. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  299. package/dist/features/products/components/ProductFilters.d.ts +7 -1
  300. package/dist/features/products/components/ProductFilters.js +11 -8
  301. package/dist/features/products/components/ProductForm.js +18 -16
  302. package/dist/features/products/components/ProductGalleryClient.js +2 -1
  303. package/dist/features/products/components/ProductGrid.js +12 -15
  304. package/dist/features/products/components/ProductsIndexListing.js +16 -52
  305. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  306. package/dist/features/products/repository/products.repository.d.ts +4 -0
  307. package/dist/features/products/repository/products.repository.js +22 -3
  308. package/dist/features/products/schemas/firestore.d.ts +7 -1
  309. package/dist/features/products/schemas/index.d.ts +56 -56
  310. package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
  311. package/dist/features/products/types/index.d.ts +4 -0
  312. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  313. package/dist/features/promotions/schemas/index.d.ts +6 -6
  314. package/dist/features/reviews/actions/review-actions.js +6 -5
  315. package/dist/features/reviews/api/[id]/route.js +4 -3
  316. package/dist/features/reviews/components/ReviewDetailPageView.js +2 -2
  317. package/dist/features/reviews/components/ReviewDetailShell.js +6 -3
  318. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  319. package/dist/features/reviews/schemas/index.d.ts +6 -6
  320. package/dist/features/scams/components/ScamProfileView.js +19 -10
  321. package/dist/features/scams/components/ScamRegistryView.js +2 -1
  322. package/dist/features/search/components/Search.d.ts +1 -1
  323. package/dist/features/search/components/Search.js +56 -49
  324. package/dist/features/search/schemas/index.d.ts +5 -5
  325. package/dist/features/seller/actions/offer-actions.js +11 -9
  326. package/dist/features/seller/components/SellerAddressesView.js +6 -4
  327. package/dist/features/seller/components/SellerBidsView.js +2 -2
  328. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  329. package/dist/features/seller/components/SellerOffersPanel.js +6 -1
  330. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  331. package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -3
  332. package/dist/features/seller/components/SellerPreOrdersView.js +5 -4
  333. package/dist/features/seller/components/SellerPrizeDrawsView.js +5 -4
  334. package/dist/features/seller/components/SellerProductShell.d.ts +19 -1
  335. package/dist/features/seller/components/SellerProductShell.js +75 -9
  336. package/dist/features/seller/components/SellerProductsView.js +10 -11
  337. package/dist/features/seller/components/SellerShippingView.js +3 -3
  338. package/dist/features/seller/components/SellerSidebar.js +10 -7
  339. package/dist/features/seller/components/SellerStorefrontView.js +3 -3
  340. package/dist/features/seller/schemas/index.d.ts +4 -4
  341. package/dist/features/shell/FormShell.js +2 -1
  342. package/dist/features/shell/QuickFormDrawer.js +4 -3
  343. package/dist/features/shell/StepForm.js +4 -3
  344. package/dist/features/stores/actions/store-query-actions.js +4 -3
  345. package/dist/features/stores/components/StoreAboutView.js +2 -1
  346. package/dist/features/stores/components/StoreAuctionsListing.js +43 -64
  347. package/dist/features/stores/components/StoreDetailLayoutView.js +18 -4
  348. package/dist/features/stores/components/StorePreOrdersListing.js +33 -57
  349. package/dist/features/stores/components/StoreProductsListing.js +16 -49
  350. package/dist/features/stores/components/StoresIndexListing.js +2 -2
  351. package/dist/features/stores/schemas/index.d.ts +2 -2
  352. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +8 -7
  353. package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +5 -5
  354. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +6 -6
  355. package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -5
  356. package/dist/index.d.ts +27 -3
  357. package/dist/index.js +1743 -1725
  358. package/dist/monitoring/server-logger.js +5 -9
  359. package/dist/next/api/apiHandler.js +56 -37
  360. package/dist/next/components/GlobalError.js +2 -1
  361. package/dist/next/routing/route-map.d.ts +41 -0
  362. package/dist/next/routing/route-map.js +17 -0
  363. package/dist/react/ErrorBoundary.js +2 -1
  364. package/dist/react/contexts/SessionContext.js +38 -28
  365. package/dist/react/hooks/useCamera.d.ts +1 -1
  366. package/dist/react/hooks/useCamera.js +8 -7
  367. package/dist/seed/products-auctions-seed-data.js +40 -40
  368. package/dist/seed/products-preorders-seed-data.js +16 -16
  369. package/dist/seed/products-prize-draws-seed-data.js +4 -4
  370. package/dist/seed/products-standard-seed-data.js +202 -202
  371. package/dist/seed/site-settings-seed-data.js +6 -0
  372. package/dist/server-entry.d.ts +3 -0
  373. package/dist/server-entry.js +3 -0
  374. package/dist/server.d.ts +12 -0
  375. package/dist/server.js +15 -0
  376. package/dist/tailwind-utilities.css +1 -1
  377. package/dist/ui/DataTable.js +28 -7
  378. package/dist/ui/components/Button.d.ts +8 -1
  379. package/dist/ui/components/Button.js +47 -8
  380. package/dist/ui/components/CollageLightbox.d.ts +18 -0
  381. package/dist/ui/components/CollageLightbox.js +41 -0
  382. package/dist/ui/components/Dropdown.js +7 -6
  383. package/dist/ui/components/ImageLightbox.d.ts +7 -1
  384. package/dist/ui/components/ImageLightbox.js +15 -5
  385. package/dist/ui/components/PageLoader.js +4 -3
  386. package/dist/ui/components/PaginatedMultiSelect.d.ts +28 -0
  387. package/dist/ui/components/PaginatedMultiSelect.js +141 -0
  388. package/dist/ui/components/PaginatedMultiSelect.style.css +272 -0
  389. package/dist/ui/components/Semantic.js +1 -1
  390. package/dist/ui/components/SideDrawer.js +17 -15
  391. package/dist/ui/components/index.style.css +1 -0
  392. package/dist/ui/index.d.ts +2 -0
  393. package/dist/ui/index.js +1 -0
  394. package/dist/utils/number.formatter.js +5 -13
  395. package/dist/utils/string.formatter.js +21 -18
  396. package/dist/validation/schemas.d.ts +2 -2
  397. package/package.json +1 -1
@@ -33,9 +33,9 @@ export declare const consultationBookingSchema: z.ZodObject<{
33
33
  createdAt?: string | undefined;
34
34
  adminNote?: string | undefined;
35
35
  message?: string | undefined;
36
- mode?: "online" | "phone" | "in_person" | undefined;
37
- userId?: string | undefined;
38
36
  phone?: string | undefined;
37
+ mode?: "phone" | "online" | "in_person" | undefined;
38
+ userId?: string | undefined;
39
39
  concern?: string[] | undefined;
40
40
  preferredDate?: string | undefined;
41
41
  preferredTime?: string | undefined;
@@ -47,9 +47,9 @@ export declare const consultationBookingSchema: z.ZodObject<{
47
47
  status?: "pending" | "completed" | "confirmed" | "cancelled" | "no_show" | undefined;
48
48
  adminNote?: string | undefined;
49
49
  message?: string | undefined;
50
- mode?: "online" | "phone" | "in_person" | undefined;
51
- userId?: string | undefined;
52
50
  phone?: string | undefined;
51
+ mode?: "phone" | "online" | "in_person" | undefined;
52
+ userId?: string | undefined;
53
53
  concern?: string[] | undefined;
54
54
  preferredDate?: string | undefined;
55
55
  preferredTime?: string | undefined;
@@ -71,8 +71,8 @@ export declare const bookConsultationSchema: z.ZodObject<{
71
71
  name: string;
72
72
  concern: string[];
73
73
  message?: string | undefined;
74
- mode?: "online" | "phone" | "in_person" | undefined;
75
74
  phone?: string | undefined;
75
+ mode?: "phone" | "online" | "in_person" | undefined;
76
76
  preferredDate?: string | undefined;
77
77
  preferredTime?: string | undefined;
78
78
  }, {
@@ -80,8 +80,8 @@ export declare const bookConsultationSchema: z.ZodObject<{
80
80
  name: string;
81
81
  concern: string[];
82
82
  message?: string | undefined;
83
- mode?: "online" | "phone" | "in_person" | undefined;
84
83
  phone?: string | undefined;
84
+ mode?: "phone" | "online" | "in_person" | undefined;
85
85
  preferredDate?: string | undefined;
86
86
  preferredTime?: string | undefined;
87
87
  }>;
@@ -1,6 +1,8 @@
1
1
  import { getProviders } from "../../contracts";
2
2
  import { serverLogger } from "../../monitoring";
3
3
  import { currentYear, formatCurrency, formatDateTime, nowMs, } from "../../utils";
4
+ const EMAIL_STYLE_MUTED = "color: #666; font-size: 14px;";
5
+ const EMAIL_STYLE_BODY = "color: #333; font-size: 14px;";
4
6
  function getSiteName() {
5
7
  return process.env.NEXT_PUBLIC_SITE_NAME?.trim() || "App";
6
8
  }
@@ -74,134 +76,93 @@ export async function sendPasswordResetEmailWithLink(email, resetLink) {
74
76
  throw error;
75
77
  }
76
78
  }
79
+ function buildOrderItemsHtml(items, productTitle, quantity, currency) {
80
+ if (items && items.length > 1) {
81
+ return `
82
+ <table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
83
+ <thead>
84
+ <tr style="background-color: #e9ecef;">
85
+ <th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
86
+ <th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
87
+ <th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
88
+ </tr>
89
+ </thead>
90
+ <tbody>
91
+ ${items.map((item, index) => `
92
+ <tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
93
+ <td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
94
+ <td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
95
+ <td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
96
+ </tr>`).join("")}
97
+ </tbody>
98
+ </table>`;
99
+ }
100
+ return `
101
+ <tr>
102
+ <td style="${EMAIL_STYLE_MUTED}">Product</td>
103
+ <td style="${EMAIL_STYLE_BODY}">${productTitle}</td>
104
+ </tr>
105
+ <tr>
106
+ <td style="${EMAIL_STYLE_MUTED}">Quantity</td>
107
+ <td style="${EMAIL_STYLE_BODY}">${quantity}</td>
108
+ </tr>`;
109
+ }
110
+ function buildOrderConfirmationHtml(params) {
111
+ const { userName, orderId, formattedTotal, shippingAddress, paymentMethod, orderUrl, itemsHtml, siteName, items } = params;
112
+ return `
113
+ <!DOCTYPE html><html>
114
+ <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Order Confirmation</title></head>
115
+ <body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
116
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
117
+ <tr><td align="center">
118
+ <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
119
+ <tr><td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
120
+ <p style="font-size: 48px; margin: 0 0 12px;">✅</p>
121
+ <h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
122
+ </td></tr>
123
+ <tr><td style="padding: 40px;">
124
+ <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
125
+ <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">Thank you for your order! We've received it and will process it shortly.</p>
126
+ <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
127
+ <tr><td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td></tr>
128
+ <tr><td style="color: #666; font-size: 14px; width: 40%;">Order ID</td><td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td></tr>
129
+ ${items && items.length > 1
130
+ ? `<tr><td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2"><div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>${itemsHtml}</td></tr>`
131
+ : itemsHtml}
132
+ <tr><td style="${EMAIL_STYLE_MUTED}">Total</td><td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td></tr>
133
+ <tr><td style="${EMAIL_STYLE_MUTED}">Payment</td><td style="${EMAIL_STYLE_BODY}">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td></tr>
134
+ <tr><td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td><td style="${EMAIL_STYLE_BODY}">${shippingAddress}</td></tr>
135
+ </table>
136
+ <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
137
+ <tr><td align="center">
138
+ <a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">View Order</a>
139
+ </td></tr>
140
+ </table>
141
+ <p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">We'll send you another email when your order is shipped.</p>
142
+ </td></tr>
143
+ <tr><td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
144
+ <p style="color: #999; font-size: 12px; margin: 0;">© ${currentYear()} ${siteName}. All rights reserved.</p>
145
+ </td></tr>
146
+ </table>
147
+ </td></tr>
148
+ </table>
149
+ </body></html>`;
150
+ }
77
151
  export async function sendOrderConfirmationEmail(params) {
78
152
  const siteName = getSiteName();
79
153
  const siteUrl = getSiteUrl();
80
154
  const { to, userName, orderId, productTitle, quantity, totalPrice, currency, shippingAddress, paymentMethod, items, } = params;
81
155
  const orderUrl = `${siteUrl}/user/orders/view/${orderId}`;
82
156
  const formattedTotal = formatCurrency(totalPrice, currency);
83
- const itemsHtml = items && items.length > 1
84
- ? `
85
- <table width="100%" cellpadding="8" cellspacing="0" border="0" style="border-collapse: collapse; margin-bottom: 8px;">
86
- <thead>
87
- <tr style="background-color: #e9ecef;">
88
- <th style="text-align: left; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Product</th>
89
- <th style="text-align: center; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Qty</th>
90
- <th style="text-align: right; font-size: 12px; font-weight: 600; color: #666; text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 12px;">Amount</th>
91
- </tr>
92
- </thead>
93
- <tbody>
94
- ${items
95
- .map((item, index) => `
96
- <tr style="background-color: ${index % 2 === 0 ? "#ffffff" : "#f8f9fa"}; border-top: 1px solid #e9ecef;">
97
- <td style="font-size: 14px; color: #333; padding: 8px 12px;">${item.productTitle}</td>
98
- <td style="font-size: 14px; color: #333; text-align: center; padding: 8px 12px;">${item.quantity}</td>
99
- <td style="font-size: 14px; color: #333; text-align: right; padding: 8px 12px;">${formatCurrency(item.totalPrice, currency)}</td>
100
- </tr>`)
101
- .join("")}
102
- </tbody>
103
- </table>`
104
- : `
105
- <tr>
106
- <td style="color: #666; font-size: 14px;">Product</td>
107
- <td style="color: #333; font-size: 14px;">${productTitle}</td>
108
- </tr>
109
- <tr>
110
- <td style="color: #666; font-size: 14px;">Quantity</td>
111
- <td style="color: #333; font-size: 14px;">${quantity}</td>
112
- </tr>`;
157
+ const itemsHtml = buildOrderItemsHtml(items, productTitle, quantity, currency);
113
158
  const itemsText = items && items.length > 1
114
- ? items
115
- .map((item) => ` • ${item.productTitle} × ${item.quantity} — ${formatCurrency(item.totalPrice, currency)}`)
116
- .join("\n")
159
+ ? items.map((item) => ` • ${item.productTitle} × ${item.quantity} — ${formatCurrency(item.totalPrice, currency)}`).join("\n")
117
160
  : ` Product: ${productTitle}\n Quantity: ${quantity}`;
118
161
  try {
119
162
  const { data, error } = await sendConfiguredEmail({
120
163
  to,
121
164
  subject: `Order Confirmed — ${orderId}`,
122
- html: `
123
- <!DOCTYPE html>
124
- <html>
125
- <head>
126
- <meta charset="utf-8">
127
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
128
- <title>Order Confirmation</title>
129
- </head>
130
- <body style="margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background-color: #f5f5f5;">
131
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f5f5f5; padding: 40px 0;">
132
- <tr>
133
- <td align="center">
134
- <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
135
- <tr>
136
- <td style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); padding: 40px; text-align: center;">
137
- <p style="font-size: 48px; margin: 0 0 12px;">✅</p>
138
- <h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 600;">Order Confirmed!</h1>
139
- </td>
140
- </tr>
141
- <tr>
142
- <td style="padding: 40px;">
143
- <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 20px;">Hi ${userName},</p>
144
- <p style="color: #333; font-size: 16px; line-height: 1.6; margin: 0 0 24px;">
145
- Thank you for your order! We've received it and will process it shortly.
146
- </p>
147
- <table width="100%" cellpadding="12" cellspacing="0" border="0" style="background-color: #f8f9fa; border-radius: 8px; margin-bottom: 24px;">
148
- <tr>
149
- <td style="color: #666; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid #e9ecef;" colspan="2">Order Details</td>
150
- </tr>
151
- <tr>
152
- <td style="color: #666; font-size: 14px; width: 40%;">Order ID</td>
153
- <td style="color: #333; font-size: 14px; font-weight: 600;">${orderId}</td>
154
- </tr>
155
- ${items && items.length > 1
156
- ? `
157
- <tr>
158
- <td style="color: #666; font-size: 14px; vertical-align: top;" colspan="2">
159
- <div style="font-weight: 600; margin-bottom: 8px;">Items (${items.length})</div>
160
- ${itemsHtml}
161
- </td>
162
- </tr>`
163
- : itemsHtml}
164
- <tr>
165
- <td style="color: #666; font-size: 14px;">Total</td>
166
- <td style="color: #333; font-size: 14px; font-weight: 700;">${formattedTotal}</td>
167
- </tr>
168
- <tr>
169
- <td style="color: #666; font-size: 14px;">Payment</td>
170
- <td style="color: #333; font-size: 14px;">${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}</td>
171
- </tr>
172
- <tr>
173
- <td style="color: #666; font-size: 14px; vertical-align: top;">Ship to</td>
174
- <td style="color: #333; font-size: 14px;">${shippingAddress}</td>
175
- </tr>
176
- </table>
177
- <table width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0;">
178
- <tr>
179
- <td align="center">
180
- <a href="${orderUrl}" style="display: inline-block; padding: 14px 40px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 16px; font-weight: 600;">
181
- View Order
182
- </a>
183
- </td>
184
- </tr>
185
- </table>
186
- <p style="color: #999; font-size: 13px; line-height: 1.6; margin: 0;">
187
- We'll send you another email when your order is shipped.
188
- </p>
189
- </td>
190
- </tr>
191
- <tr>
192
- <td style="background-color: #f8f9fa; padding: 24px; text-align: center; border-top: 1px solid #eee;">
193
- <p style="color: #999; font-size: 12px; margin: 0;">
194
- © ${currentYear()} ${siteName}. All rights reserved.
195
- </p>
196
- </td>
197
- </tr>
198
- </table>
199
- </td>
200
- </tr>
201
- </table>
202
- </body>
203
- </html>
204
- `,
165
+ html: buildOrderConfirmationHtml({ userName, orderId, formattedTotal, shippingAddress, paymentMethod, orderUrl, itemsHtml, siteName, items }),
205
166
  text: `Hi ${userName},\n\nYour order ${orderId} has been confirmed!\n\n${itemsText}\nTotal: ${formattedTotal}\nPayment: ${paymentMethod === "cod" ? "Cash on Delivery" : "Online Payment"}\nShip to: ${shippingAddress}\n\nView your order: ${orderUrl}\n\n© ${currentYear()} ${siteName}`,
206
167
  });
207
168
  if (error) {
@@ -6,12 +6,22 @@ import { Alert, Button, Div, Heading, Input, Span, StackedViewShell, Text, } fro
6
6
  import { apiClient } from "../../../http";
7
7
  import { useCopilotChat } from "../hooks/useCopilotChat";
8
8
  import { THEME_CONSTANTS } from "../../../tokens";
9
+ const LBL_CONVERSATION_ID = "Conversation ID";
9
10
  function MessageBubble({ msg }) {
10
11
  const isUser = msg.role === "user";
11
12
  return (_jsx(Div, { className: `flex ${isUser ? "justify-end" : "justify-start"}`, children: _jsxs(Div, { className: `max-w-[80%] rounded-2xl px-4 py-2.5 text-sm ${isUser
12
13
  ? "bg-primary text-white rounded-tr-sm"
13
14
  : "bg-neutral-100 dark:bg-slate-700 text-neutral-900 dark:text-neutral-100 rounded-tl-sm"}`, children: [_jsx(Text, { className: "whitespace-pre-wrap text-sm leading-relaxed", children: msg.content }), msg.durationMs ? (_jsxs(Span, { className: "mt-1 block text-xs opacity-60", children: [(msg.durationMs / 1000).toFixed(1), "s"] })) : null] }) }));
14
15
  }
16
+ function renderCopilotChatPanel(props) {
17
+ const { messages, conversationId, isLoading, error, input, setInput, labels, messagesEndRef, handleSubmit } = props;
18
+ return (_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels?.conversationId ?? LBL_CONVERSATION_ID, ": ", conversationId] }) }), _jsxs(Div, { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [messages.length === 0 ? (_jsxs(Div, { className: "flex flex-col items-center justify-center h-full text-center", children: [_jsx(Text, { className: "font-medium", children: labels?.noMessages ?? "No messages yet" }), _jsx(Text, { variant: "secondary", className: "text-sm mt-1", children: labels?.noMessagesDesc ?? "Ask anything to get started" })] })) : null, messages.map((msg) => _jsx(MessageBubble, { msg: msg }, msg.id)), isLoading ? (_jsx(Div, { className: "flex justify-start", children: _jsx(Div, { className: "rounded-2xl rounded-tl-sm bg-neutral-100 dark:bg-slate-700 px-4 py-2.5", children: _jsx(Span, { className: "text-sm opacity-60 animate-pulse", children: "Thinking..." }) }) })) : null, error ? _jsx(Text, { className: "text-center text-sm text-red-500", children: labels?.errorLabel ?? "An error occurred. Please try again." }) : null, _jsx("div", { ref: messagesEndRef })] }), _jsx(Div, { className: "border-t border-neutral-200 dark:border-slate-700 p-3", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex gap-2", children: [_jsx("input", { type: "text", value: input, onChange: (e) => setInput(e.target.value), placeholder: labels?.inputPlaceholder ?? "Ask anything...", disabled: isLoading, className: "flex-1 h-10 rounded-lg border border-neutral-200 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 text-sm outline-none focus:ring-2 ring-primary/20 transition disabled:opacity-60" }), _jsx(Button, { type: "submit", variant: "primary", disabled: isLoading || !input.trim(), className: "shrink-0", children: isLoading ? labels?.sendingButton ?? "Sending..." : labels?.sendButton ?? "Send" })] }) })] }));
19
+ }
20
+ function renderCopilotHistoryPanel(props) {
21
+ const { historyQuery, conversationInput, setConversationInput, loadConversation, labels } = props;
22
+ return (_jsxs(Div, { className: "rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 space-y-3", children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold", children: labels?.historyTitle ?? "Conversation History" }), _jsxs("form", { className: "space-y-2", onSubmit: (e) => { e.preventDefault(); if (!conversationInput.trim())
23
+ return; loadConversation(conversationInput.trim()); }, children: [_jsx(Input, { label: labels?.conversationId ?? LBL_CONVERSATION_ID, value: conversationInput, onChange: (e) => setConversationInput(e.target.value), placeholder: "conv_..." }), _jsx(Button, { type: "submit", variant: "secondary", size: "sm", className: "w-full", children: labels?.loadConversation ?? "Load conversation" })] }), historyQuery.error ? (_jsx(Alert, { variant: "warning", title: "History unavailable", children: historyQuery.error instanceof Error ? historyQuery.error.message : "Could not load history" })) : null, _jsxs(Div, { className: "max-h-72 overflow-y-auto space-y-2", children: [(historyQuery.data?.messages ?? []).map((log, index) => (_jsxs(Div, { className: "rounded-lg border border-neutral-200 dark:border-slate-700 p-2", children: [_jsx(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: new Date(log.createdAt).toLocaleString() }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3}`, children: ["Q: ", log.prompt] }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3} text-neutral-600 dark:text-zinc-300`, children: ["A: ", log.response] })] }, `${log.createdAt}-${index}`))), !historyQuery.isLoading && (historyQuery.data?.messages?.length ?? 0) === 0 ? (_jsx(Text, { variant: "secondary", className: "text-sm", children: "No server history found for this conversation yet." })) : null] })] }));
24
+ }
15
25
  export function AdminCopilotView({ endpoint, historyEndpoint = "/api/copilot/history", renderHeader, labels = {}, className = "", }) {
16
26
  const [input, setInput] = useState("");
17
27
  const [conversationInput, setConversationInput] = useState("");
@@ -34,11 +44,11 @@ export function AdminCopilotView({ endpoint, historyEndpoint = "/api/copilot/his
34
44
  };
35
45
  return (_jsx(StackedViewShell, { portal: "admin", title: labels.title ?? "AI Copilot", className: className, sections: [
36
46
  renderHeader ? (renderHeader(startNewConversation)) : (_jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsx(Heading, { level: 2, children: labels.title ?? "AI Copilot" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: startNewConversation, children: labels.newConversation ?? "New Conversation" })] })),
37
- _jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-[2fr,1fr] gap-4", children: [_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels.conversationId ?? "Conversation ID", ": ", conversationId] }) }), _jsxs(Div, { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [messages.length === 0 ? (_jsxs(Div, { className: "flex flex-col items-center justify-center h-full text-center", children: [_jsx(Text, { className: "font-medium", children: labels.noMessages ?? "No messages yet" }), _jsx(Text, { variant: "secondary", className: "text-sm mt-1", children: labels.noMessagesDesc ?? "Ask anything to get started" })] })) : null, messages.map((msg) => (_jsx(MessageBubble, { msg: msg }, msg.id))), isLoading ? (_jsx(Div, { className: "flex justify-start", children: _jsx(Div, { className: "rounded-2xl rounded-tl-sm bg-neutral-100 dark:bg-slate-700 px-4 py-2.5", children: _jsx(Span, { className: "text-sm opacity-60 animate-pulse", children: "Thinking..." }) }) })) : null, error ? (_jsx(Text, { className: "text-center text-sm text-red-500", children: labels.errorLabel ?? "An error occurred. Please try again." })) : null, _jsx("div", { ref: messagesEndRef })] }), _jsx(Div, { className: "border-t border-neutral-200 dark:border-slate-700 p-3", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex gap-2", children: [_jsx("input", { type: "text", value: input, onChange: (event) => setInput(event.target.value), placeholder: labels.inputPlaceholder ?? "Ask anything...", disabled: isLoading, className: "flex-1 h-10 rounded-lg border border-neutral-200 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 text-sm outline-none focus:ring-2 ring-primary/20 transition disabled:opacity-60" }), _jsx(Button, { type: "submit", variant: "primary", disabled: isLoading || !input.trim(), className: "shrink-0", children: isLoading ? labels.sendingButton ?? "Sending..." : labels.sendButton ?? "Send" })] }) })] }), _jsxs(Div, { className: "rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 space-y-3", children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold", children: labels.historyTitle ?? "Conversation History" }), _jsxs("form", { className: "space-y-2", onSubmit: (event) => {
47
+ _jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-[2fr,1fr] gap-4", children: [_jsxs(Div, { className: "flex flex-col rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 h-[calc(100vh-300px)]", children: [_jsx(Div, { className: "border-b border-neutral-200 dark:border-slate-700 p-3", children: _jsxs(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: [labels.conversationId ?? LBL_CONVERSATION_ID, ": ", conversationId] }) }), _jsxs(Div, { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [messages.length === 0 ? (_jsxs(Div, { className: "flex flex-col items-center justify-center h-full text-center", children: [_jsx(Text, { className: "font-medium", children: labels.noMessages ?? "No messages yet" }), _jsx(Text, { variant: "secondary", className: "text-sm mt-1", children: labels.noMessagesDesc ?? "Ask anything to get started" })] })) : null, messages.map((msg) => (_jsx(MessageBubble, { msg: msg }, msg.id))), isLoading ? (_jsx(Div, { className: "flex justify-start", children: _jsx(Div, { className: "rounded-2xl rounded-tl-sm bg-neutral-100 dark:bg-slate-700 px-4 py-2.5", children: _jsx(Span, { className: "text-sm opacity-60 animate-pulse", children: "Thinking..." }) }) })) : null, error ? (_jsx(Text, { className: "text-center text-sm text-red-500", children: labels.errorLabel ?? "An error occurred. Please try again." })) : null, _jsx("div", { ref: messagesEndRef })] }), _jsx(Div, { className: "border-t border-neutral-200 dark:border-slate-700 p-3", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex gap-2", children: [_jsx("input", { type: "text", value: input, onChange: (event) => setInput(event.target.value), placeholder: labels.inputPlaceholder ?? "Ask anything...", disabled: isLoading, className: "flex-1 h-10 rounded-lg border border-neutral-200 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 text-sm outline-none focus:ring-2 ring-primary/20 transition disabled:opacity-60" }), _jsx(Button, { type: "submit", variant: "primary", disabled: isLoading || !input.trim(), className: "shrink-0", children: isLoading ? labels.sendingButton ?? "Sending..." : labels.sendButton ?? "Send" })] }) })] }), _jsxs(Div, { className: "rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4 space-y-3", children: [_jsx(Heading, { level: 3, className: "text-sm font-semibold", children: labels.historyTitle ?? "Conversation History" }), _jsxs("form", { className: "space-y-2", onSubmit: (event) => {
38
48
  event.preventDefault();
39
49
  if (!conversationInput.trim())
40
50
  return;
41
51
  loadConversation(conversationInput.trim());
42
- }, children: [_jsx(Input, { label: labels.conversationId ?? "Conversation ID", value: conversationInput, onChange: (event) => setConversationInput(event.target.value), placeholder: "conv_..." }), _jsx(Button, { type: "submit", variant: "secondary", size: "sm", className: "w-full", children: labels.loadConversation ?? "Load conversation" })] }), historyQuery.error ? (_jsx(Alert, { variant: "warning", title: "History unavailable", children: historyQuery.error instanceof Error ? historyQuery.error.message : "Could not load history" })) : null, _jsxs(Div, { className: "max-h-72 overflow-y-auto space-y-2", children: [(historyQuery.data?.messages ?? []).map((log, index) => (_jsxs(Div, { className: "rounded-lg border border-neutral-200 dark:border-slate-700 p-2", children: [_jsx(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: new Date(log.createdAt).toLocaleString() }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3}`, children: ["Q: ", log.prompt] }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3} text-neutral-600 dark:text-zinc-300`, children: ["A: ", log.response] })] }, `${log.createdAt}-${index}`))), !historyQuery.isLoading && (historyQuery.data?.messages?.length ?? 0) === 0 ? (_jsx(Text, { variant: "secondary", className: "text-sm", children: "No server history found for this conversation yet." })) : null] })] })] }),
52
+ }, children: [_jsx(Input, { label: labels.conversationId ?? LBL_CONVERSATION_ID, value: conversationInput, onChange: (event) => setConversationInput(event.target.value), placeholder: "conv_..." }), _jsx(Button, { type: "submit", variant: "secondary", size: "sm", className: "w-full", children: labels.loadConversation ?? "Load conversation" })] }), historyQuery.error ? (_jsx(Alert, { variant: "warning", title: "History unavailable", children: historyQuery.error instanceof Error ? historyQuery.error.message : "Could not load history" })) : null, _jsxs(Div, { className: "max-h-72 overflow-y-auto space-y-2", children: [(historyQuery.data?.messages ?? []).map((log, index) => (_jsxs(Div, { className: "rounded-lg border border-neutral-200 dark:border-slate-700 p-2", children: [_jsx(Text, { className: "text-xs font-medium text-neutral-500 dark:text-zinc-400", children: new Date(log.createdAt).toLocaleString() }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3}`, children: ["Q: ", log.prompt] }), _jsxs(Text, { className: `text-sm mt-1 ${THEME_CONSTANTS.utilities.textClamp3} text-neutral-600 dark:text-zinc-300`, children: ["A: ", log.response] })] }, `${log.createdAt}-${index}`))), !historyQuery.isLoading && (historyQuery.data?.messages?.length ?? 0) === 0 ? (_jsx(Text, { variant: "secondary", className: "text-sm", children: "No server history found for this conversation yet." })) : null] })] })] }),
43
53
  ] }));
44
54
  }
@@ -10,15 +10,18 @@
10
10
  */
11
11
  import { NextResponse } from "next/server.js";
12
12
  import { getProviders } from "../../../../contracts";
13
+ const ERR_INQUIRY_ID_REQUIRED = "Inquiry ID is required";
14
+ const ERR_DB_NOT_CONFIGURED = "Database provider not configured";
15
+ const ERR_INTERNAL_SERVER_ERROR = "Internal server error";
13
16
  export async function GET(request, { params }) {
14
17
  try {
15
18
  const { id } = await params;
16
19
  if (!id) {
17
- return NextResponse.json({ success: false, error: "Inquiry ID required" }, { status: 400 });
20
+ return NextResponse.json({ success: false, error: ERR_INQUIRY_ID_REQUIRED }, { status: 400 });
18
21
  }
19
22
  const { db } = getProviders();
20
23
  if (!db)
21
- return NextResponse.json({ success: false, error: "DB not configured" }, { status: 503 });
24
+ return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
22
25
  const repo = db.getRepository("corporate_inquiries");
23
26
  const inquiry = await repo.findById(id);
24
27
  if (!inquiry) {
@@ -32,7 +35,7 @@ export async function GET(request, { params }) {
32
35
  catch (error) {
33
36
  return NextResponse.json({
34
37
  success: false,
35
- error: error instanceof Error ? error.message : "Internal server error",
38
+ error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
36
39
  }, { status: 500 });
37
40
  }
38
41
  }
@@ -40,12 +43,12 @@ export async function PATCH(request, { params }) {
40
43
  try {
41
44
  const { id } = await params;
42
45
  if (!id) {
43
- return NextResponse.json({ success: false, error: "Inquiry ID required" }, { status: 400 });
46
+ return NextResponse.json({ success: false, error: ERR_INQUIRY_ID_REQUIRED }, { status: 400 });
44
47
  }
45
48
  const body = await request.json();
46
49
  const { db } = getProviders();
47
50
  if (!db)
48
- return NextResponse.json({ success: false, error: "DB not configured" }, { status: 503 });
51
+ return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
49
52
  const repo = db.getRepository("corporate_inquiries");
50
53
  const updated = await repo.update(id, body);
51
54
  if (!updated) {
@@ -59,7 +62,7 @@ export async function PATCH(request, { params }) {
59
62
  catch (error) {
60
63
  return NextResponse.json({
61
64
  success: false,
62
- error: error instanceof Error ? error.message : "Internal server error",
65
+ error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
63
66
  }, { status: 500 });
64
67
  }
65
68
  }
@@ -67,11 +70,11 @@ export async function DELETE(request, { params }) {
67
70
  try {
68
71
  const { id } = await params;
69
72
  if (!id) {
70
- return NextResponse.json({ success: false, error: "Inquiry ID required" }, { status: 400 });
73
+ return NextResponse.json({ success: false, error: ERR_INQUIRY_ID_REQUIRED }, { status: 400 });
71
74
  }
72
75
  const { db } = getProviders();
73
76
  if (!db)
74
- return NextResponse.json({ success: false, error: "DB not configured" }, { status: 503 });
77
+ return NextResponse.json({ success: false, error: ERR_DB_NOT_CONFIGURED }, { status: 503 });
75
78
  const repo = db.getRepository("corporate_inquiries");
76
79
  await repo.delete(id);
77
80
  return NextResponse.json({
@@ -82,7 +85,7 @@ export async function DELETE(request, { params }) {
82
85
  catch (error) {
83
86
  return NextResponse.json({
84
87
  success: false,
85
- error: error instanceof Error ? error.message : "Internal server error",
88
+ error: error instanceof Error ? error.message : ERR_INTERNAL_SERVER_ERROR,
86
89
  }, { status: 500 });
87
90
  }
88
91
  }
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { Button, Div, Input, Text, Textarea } from "../../../ui";
5
+ const CLS_INPUT = "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm";
5
6
  export function CorporateInquiryForm({ onSubmit, isPending, }) {
6
7
  const [form, setForm] = React.useState({
7
8
  companyName: "",
@@ -32,5 +33,5 @@ export function CorporateInquiryForm({ onSubmit, isPending, }) {
32
33
  e.preventDefault();
33
34
  await onSubmit(form);
34
35
  }
35
- return (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsxs(Div, { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [_jsx(Input, { name: "companyName", type: "text", placeholder: "Company name", value: form.companyName, onChange: handleChange, required: true, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "contactPerson", type: "text", placeholder: "Contact person", value: form.contactPerson, onChange: handleChange, required: true, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "designation", type: "text", placeholder: "Designation (optional)", value: form.designation ?? "", onChange: handleChange, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "email", type: "email", placeholder: "Business email", value: form.email, onChange: handleChange, required: true, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "phone", type: "tel", placeholder: "Phone number", value: form.phone, onChange: handleChange, required: true, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "units", type: "number", placeholder: "Number of units", value: form.units, onChange: handleChange, min: 1, required: true, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "budgetPerUnit", type: "number", placeholder: "Budget per unit (optional)", value: form.budgetPerUnit ?? "", onChange: handleChange, min: 0, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Input, { name: "deliveryDateRequired", type: "date", placeholder: "Required by (optional)", value: form.deliveryDateRequired ?? "", onChange: handleChange, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" })] }), _jsxs(Div, { className: "flex items-center gap-2 text-sm text-neutral-700", children: [_jsx("input", { name: "customBranding", type: "checkbox", checked: form.customBranding, onChange: handleChange, className: "h-4 w-4 rounded border-neutral-300" }), _jsx(Text, { className: "text-sm text-neutral-700", children: "Custom branding required" })] }), _jsx(Textarea, { name: "message", placeholder: "Additional requirements (optional)", value: form.message ?? "", onChange: handleChange, rows: 4, className: "w-full rounded-md border border-neutral-300 px-3 py-2 text-sm" }), _jsx(Button, { type: "submit", disabled: isPending, variant: "primary", className: "w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-white transition hover:bg-primary/90 disabled:opacity-60", children: isPending ? "Submitting..." : "Submit Inquiry" })] }));
36
+ return (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsxs(Div, { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [_jsx(Input, { name: "companyName", type: "text", placeholder: "Company name", value: form.companyName, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "contactPerson", type: "text", placeholder: "Contact person", value: form.contactPerson, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "designation", type: "text", placeholder: "Designation (optional)", value: form.designation ?? "", onChange: handleChange, className: CLS_INPUT }), _jsx(Input, { name: "email", type: "email", placeholder: "Business email", value: form.email, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "phone", type: "tel", placeholder: "Phone number", value: form.phone, onChange: handleChange, required: true, className: CLS_INPUT }), _jsx(Input, { name: "units", type: "number", placeholder: "Number of units", value: form.units, onChange: handleChange, min: 1, required: true, className: CLS_INPUT }), _jsx(Input, { name: "budgetPerUnit", type: "number", placeholder: "Budget per unit (optional)", value: form.budgetPerUnit ?? "", onChange: handleChange, min: 0, className: CLS_INPUT }), _jsx(Input, { name: "deliveryDateRequired", type: "date", placeholder: "Required by (optional)", value: form.deliveryDateRequired ?? "", onChange: handleChange, className: CLS_INPUT })] }), _jsxs(Div, { className: "flex items-center gap-2 text-sm text-neutral-700", children: [_jsx("input", { name: "customBranding", type: "checkbox", checked: form.customBranding, onChange: handleChange, className: "h-4 w-4 rounded border-neutral-300" }), _jsx(Text, { className: "text-sm text-neutral-700", children: "Custom branding required" })] }), _jsx(Textarea, { name: "message", placeholder: "Additional requirements (optional)", value: form.message ?? "", onChange: handleChange, rows: 4, className: CLS_INPUT }), _jsx(Button, { type: "submit", disabled: isPending, variant: "primary", className: "w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-white transition hover:bg-primary/90 disabled:opacity-60", children: isPending ? "Submitting..." : "Submit Inquiry" })] }));
36
37
  }
@@ -0,0 +1,12 @@
1
+ import type { FacetOption } from "../../filters/FilterFacetSection";
2
+ import type { UrlTable } from "../../filters/FilterPanel";
3
+ import type { AsyncFacetSectionProps } from "../../filters/AsyncFacetSection";
4
+ type LoadOptionsFn = AsyncFacetSectionProps["loadOptions"];
5
+ export interface DigitalCodeFiltersProps {
6
+ table: UrlTable;
7
+ categoryOptions?: FacetOption[];
8
+ loadCategoryOptions?: LoadOptionsFn;
9
+ currencyPrefix?: string;
10
+ }
11
+ export declare function DigitalCodeFilters({ table, categoryOptions, loadCategoryOptions, currencyPrefix, }: DigitalCodeFiltersProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { FilterFacetSection } from "../../filters/FilterFacetSection";
4
+ import { AsyncFacetSection } from "../../filters/AsyncFacetSection";
5
+ import { RangeFilter } from "../../filters/RangeFilter";
6
+ import { Div } from "../../../ui";
7
+ const DELIVERY_OPTIONS = [
8
+ { value: "auto-claim", label: "Instant (auto-claim)" },
9
+ { value: "manual-email", label: "Manual (sent by seller)" },
10
+ ];
11
+ export function DigitalCodeFilters({ table, categoryOptions = [], loadCategoryOptions, currencyPrefix = "₹", }) {
12
+ const selectedCategories = table.get("category")
13
+ ? table.get("category").split("|").filter(Boolean)
14
+ : [];
15
+ const selectedDelivery = table.get("deliveryMethod") ? [table.get("deliveryMethod")] : [];
16
+ return (_jsxs(Div, { children: [loadCategoryOptions ? (_jsx(AsyncFacetSection, { title: "Category", loadOptions: loadCategoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), defaultCollapsed: false })) : categoryOptions.length > 0 ? (_jsx(FilterFacetSection, { title: "Category", options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })) : null, _jsx(FilterFacetSection, { title: "Delivery Method", options: DELIVERY_OPTIONS, selected: selectedDelivery, onChange: (vals) => table.set("deliveryMethod", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(RangeFilter, { title: "Price per Code", minValue: table.get("minPrice"), maxValue: table.get("maxPrice"), onMinChange: (v) => table.set("minPrice", v), onMaxChange: (v) => table.set("maxPrice", v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 50000, step: 50, minPlaceholder: "Min price", maxPlaceholder: "Max price", defaultCollapsed: false })] }));
17
+ }
@@ -0,0 +1,4 @@
1
+ export interface DigitalCodesIndexListingProps {
2
+ initialData?: any;
3
+ }
4
+ export declare function DigitalCodesIndexListing({ initialData }: DigitalCodesIndexListingProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useCallback } from "react";
4
+ import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
+ import { useProducts } from "../../products/hooks/useProducts";
6
+ import { BulkActionBar, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Text, useToast } from "../../../ui";
7
+ import { usePendingTable } from "../../../react/hooks/usePendingTable";
8
+ import { useAuthGate } from "../../../react/hooks/useAuthGate";
9
+ import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
10
+ import { useGuestWishlist } from "../../wishlist/hooks/useGuestWishlist";
11
+ import { pushWishlistOp } from "../../cart/utils/pending-ops";
12
+ import { useCategoryTree, categoriesToFacetOptions } from "../../categories/hooks/useCategoryTree";
13
+ import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
14
+ import { sortBy } from "../../../constants/sort";
15
+ import { PRODUCT_FIELDS } from "../../../constants/field-names";
16
+ import { ROUTES } from "../../../next";
17
+ import { InteractiveProductCard } from "../../products/components/InteractiveProductCard";
18
+ import { DigitalCodeFilters } from "./DigitalCodeFilters";
19
+ import { ACTION_ID } from "../../products/constants/action-defs";
20
+ const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
21
+ const SORT_OPTIONS = [
22
+ { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
23
+ { value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
24
+ { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Price: Low to High" },
25
+ { value: sortBy(PRODUCT_FIELDS.PRICE), label: "Price: High to Low" },
26
+ ];
27
+ const FILTER_KEYS = [
28
+ TABLE_KEYS.CATEGORY,
29
+ TABLE_KEYS.DELIVERY_METHOD,
30
+ TABLE_KEYS.MIN_PRICE,
31
+ TABLE_KEYS.MAX_PRICE,
32
+ ];
33
+ export function DigitalCodesIndexListing({ initialData }) {
34
+ const table = useUrlTable({ defaults: { pageSize: "24", sort: DEFAULT_SORT } });
35
+ const { showToast } = useToast();
36
+ const { requireAuth, modalOpen, modalMessage, closeModal } = useAuthGate();
37
+ const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
38
+ const [filterOpen, setFilterOpen] = useState(false);
39
+ const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
40
+ const localWishlist = useGuestWishlist();
41
+ const { categories } = useCategoryTree();
42
+ const categoryOptions = categoriesToFacetOptions(categories);
43
+ const wishlistedIds = new Set(localWishlist.items.filter((i) => i.type === "digital-code").map((i) => i.itemId));
44
+ const { pendingTable, filterActiveCount, onFilterApply, onFilterClear, onFilterReset } = usePendingTable(table, FILTER_KEYS);
45
+ const openFilters = useCallback(() => {
46
+ onFilterReset();
47
+ setFilterOpen(true);
48
+ }, [onFilterReset]);
49
+ const applyFilters = useCallback(() => {
50
+ onFilterApply();
51
+ setFilterOpen(false);
52
+ }, [onFilterApply]);
53
+ const resetAll = useCallback(() => {
54
+ table.setMany({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "" });
55
+ onFilterClear();
56
+ setSearchInput("");
57
+ }, [table, onFilterClear]);
58
+ const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
59
+ table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
60
+ filterActiveCount > 0;
61
+ const params = {
62
+ q: table.get(TABLE_KEYS.QUERY) || undefined,
63
+ category: table.get(TABLE_KEYS.CATEGORY) || undefined,
64
+ minPrice: table.get(TABLE_KEYS.MIN_PRICE) ? Number(table.get(TABLE_KEYS.MIN_PRICE)) : undefined,
65
+ maxPrice: table.get(TABLE_KEYS.MAX_PRICE) ? Number(table.get(TABLE_KEYS.MAX_PRICE)) : undefined,
66
+ sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
67
+ page: table.getNumber(TABLE_KEYS.PAGE, 1),
68
+ perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
69
+ listingType: "digital-code",
70
+ };
71
+ const { products, totalPages, page, isLoading } = useProducts(params, { initialData });
72
+ const commitSearch = useCallback(() => {
73
+ table.set(TABLE_KEYS.QUERY, searchInput.trim());
74
+ }, [searchInput, table]);
75
+ const selection = useBulkSelection({ items: products, keyExtractor: (p) => p.id });
76
+ const gridClass = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4";
77
+ const wishlistActions = {
78
+ addToWishlist: (productId) => {
79
+ requireAuth(ACTION_ID.ADD_TO_WISHLIST, () => {
80
+ localWishlist.add(productId, "digital-code");
81
+ pushWishlistOp({ op: "add", itemId: productId, type: "digital-code" });
82
+ showToast("Added to wishlist", "success");
83
+ });
84
+ return Promise.resolve();
85
+ },
86
+ removeFromWishlist: (productId) => {
87
+ requireAuth(ACTION_ID.REMOVE_FROM_WISHLIST, () => {
88
+ localWishlist.remove(productId, "digital-code");
89
+ pushWishlistOp({ op: "remove", itemId: productId, type: "digital-code" });
90
+ showToast("Removed from wishlist", "info");
91
+ });
92
+ return Promise.resolve();
93
+ },
94
+ isWishlisted: (productId) => wishlistedIds.has(productId),
95
+ };
96
+ function handleToggleWishlist(id) {
97
+ if (wishlistActions.isWishlisted(id)) {
98
+ wishlistActions.removeFromWishlist(id);
99
+ }
100
+ else {
101
+ wishlistActions.addToWishlist(id);
102
+ }
103
+ }
104
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search digital codes\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: (e) => { if (e.key === "Enter")
105
+ commitSearch(); }, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: (v) => { if (v !== "table")
106
+ setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: gridClass, children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : products.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No digital code listings found." })) : (_jsx("div", { className: view === "list" ? "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800" : gridClass, children: products.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.DIGITAL_CODE_DETAIL(product.id)), variant: view === "list" ? "list" : "grid", isWishlisted: wishlistActions.isWishlisted(product.id), onToggleWishlist: handleToggleWishlist, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(DigitalCodeFilters, { table: pendingTable, categoryOptions: categoryOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
107
+ }
@@ -0,0 +1,6 @@
1
+ type SearchParams = Record<string, string | string[]>;
2
+ export interface DigitalCodesListViewProps {
3
+ searchParams?: SearchParams;
4
+ }
5
+ export declare function DigitalCodesListView({ searchParams }: DigitalCodesListViewProps): Promise<import("react/jsx-runtime").JSX.Element>;
6
+ export {};