@mohasinac/appkit 2.7.59 → 2.8.0

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 (311) hide show
  1. package/dist/_internal/client/features/filters/filter-load-options.d.ts +4 -5
  2. package/dist/_internal/server/features/auctions/og.js +8 -32
  3. package/dist/_internal/server/features/blog/og.js +10 -49
  4. package/dist/_internal/server/features/checkout/actions.js +6 -0
  5. package/dist/_internal/server/features/classified/og.js +9 -51
  6. package/dist/_internal/server/features/digital-code/actions.d.ts +11 -0
  7. package/dist/_internal/server/features/digital-code/actions.js +30 -0
  8. package/dist/_internal/server/features/digital-code/index.d.ts +1 -0
  9. package/dist/_internal/server/features/digital-code/index.js +1 -0
  10. package/dist/_internal/server/features/digital-code/og.js +9 -51
  11. package/dist/_internal/server/features/events/og.js +10 -49
  12. package/dist/_internal/server/features/item-requests/data.d.ts +17 -0
  13. package/dist/_internal/server/features/item-requests/data.js +20 -0
  14. package/dist/_internal/server/features/item-requests/index.d.ts +2 -0
  15. package/dist/_internal/server/features/item-requests/index.js +2 -0
  16. package/dist/_internal/server/features/item-requests/og.d.ts +40 -0
  17. package/dist/_internal/server/features/item-requests/og.js +136 -0
  18. package/dist/_internal/server/features/live/actions.d.ts +5 -0
  19. package/dist/_internal/server/features/live/actions.js +24 -0
  20. package/dist/_internal/server/features/live/index.d.ts +1 -0
  21. package/dist/_internal/server/features/live/index.js +1 -0
  22. package/dist/_internal/server/features/live/og.js +9 -51
  23. package/dist/_internal/server/features/media/contextGuards.js +19 -8
  24. package/dist/_internal/server/features/pre-orders/og.js +8 -32
  25. package/dist/_internal/server/features/prize-draws/data.d.ts +17 -0
  26. package/dist/_internal/server/features/prize-draws/data.js +20 -0
  27. package/dist/_internal/server/features/prize-draws/index.d.ts +2 -0
  28. package/dist/_internal/server/features/prize-draws/index.js +2 -0
  29. package/dist/_internal/server/features/prize-draws/og.d.ts +30 -0
  30. package/dist/_internal/server/features/prize-draws/og.js +50 -0
  31. package/dist/_internal/server/features/products/og.js +8 -33
  32. package/dist/_internal/server/features/seo/og-layout.d.ts +42 -0
  33. package/dist/_internal/server/features/seo/og-layout.js +69 -0
  34. package/dist/_internal/server/features/stores/og.js +8 -41
  35. package/dist/_internal/server/features/sublisting-categories/og.js +11 -42
  36. package/dist/client.d.ts +10 -6
  37. package/dist/client.js +7 -3
  38. package/dist/constants/index.d.ts +4 -0
  39. package/dist/constants/index.js +2 -0
  40. package/dist/constants/notification-types.d.ts +20 -0
  41. package/dist/constants/notification-types.js +37 -0
  42. package/dist/constants/pagination-presets.d.ts +39 -0
  43. package/dist/constants/pagination-presets.js +38 -0
  44. package/dist/errors/messages.d.ts +0 -4
  45. package/dist/errors/messages.js +0 -4
  46. package/dist/features/account/components/UserOffersPanel.js +1 -1
  47. package/dist/features/account/components/UserSupportView.d.ts +1 -2
  48. package/dist/features/account/components/UserSupportView.js +9 -1
  49. package/dist/features/admin/actions/admin-actions.js +16 -1
  50. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +2 -3
  51. package/dist/features/admin/components/AdminAllEventEntriesView.js +50 -83
  52. package/dist/features/admin/components/AdminBidsView.d.ts +2 -3
  53. package/dist/features/admin/components/AdminBidsView.js +64 -98
  54. package/dist/features/admin/components/AdminBlogView.d.ts +3 -7
  55. package/dist/features/admin/components/AdminBlogView.js +53 -83
  56. package/dist/features/admin/components/AdminBrandsView.d.ts +2 -3
  57. package/dist/features/admin/components/AdminBrandsView.js +84 -83
  58. package/dist/features/admin/components/AdminBundlesView.js +82 -125
  59. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -2
  60. package/dist/features/admin/components/AdminCarouselView.js +17 -52
  61. package/dist/features/admin/components/AdminCartsView.d.ts +2 -3
  62. package/dist/features/admin/components/AdminCartsView.js +39 -88
  63. package/dist/features/admin/components/AdminCategoriesView.d.ts +3 -3
  64. package/dist/features/admin/components/AdminCategoriesView.js +98 -92
  65. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  66. package/dist/features/admin/components/AdminClassifiedView.d.ts +3 -0
  67. package/dist/features/admin/components/AdminClassifiedView.js +44 -0
  68. package/dist/features/admin/components/AdminContactView.d.ts +2 -2
  69. package/dist/features/admin/components/AdminContactView.js +104 -111
  70. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -6
  71. package/dist/features/admin/components/AdminCouponsView.js +66 -86
  72. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +3 -0
  73. package/dist/features/admin/components/AdminDigitalCodesView.js +51 -0
  74. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -4
  75. package/dist/features/admin/components/AdminFaqsView.js +77 -33
  76. package/dist/features/admin/components/AdminFeaturesView.d.ts +2 -3
  77. package/dist/features/admin/components/AdminFeaturesView.js +57 -70
  78. package/dist/features/admin/components/AdminGroupedListingsView.d.ts +3 -0
  79. package/dist/features/admin/components/AdminGroupedListingsView.js +43 -0
  80. package/dist/features/admin/components/AdminHistoryView.d.ts +2 -3
  81. package/dist/features/admin/components/AdminHistoryView.js +35 -52
  82. package/dist/features/admin/components/AdminListingScaffold.d.ts +2 -2
  83. package/dist/features/admin/components/AdminListingScaffold.js +3 -3
  84. package/dist/features/admin/components/AdminLiveView.d.ts +3 -0
  85. package/dist/features/admin/components/AdminLiveView.js +50 -0
  86. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -2
  87. package/dist/features/admin/components/AdminNewsletterView.js +67 -97
  88. package/dist/features/admin/components/AdminNotificationsView.d.ts +2 -3
  89. package/dist/features/admin/components/AdminNotificationsView.js +67 -93
  90. package/dist/features/admin/components/AdminOrderEditorView.js +10 -10
  91. package/dist/features/admin/components/AdminOrdersView.d.ts +2 -3
  92. package/dist/features/admin/components/AdminOrdersView.js +93 -107
  93. package/dist/features/admin/components/AdminPayoutsView.d.ts +2 -3
  94. package/dist/features/admin/components/AdminPayoutsView.js +51 -91
  95. package/dist/features/admin/components/AdminPrizeDrawsView.d.ts +2 -3
  96. package/dist/features/admin/components/AdminPrizeDrawsView.js +39 -76
  97. package/dist/features/admin/components/AdminProductEditorView.js +3 -3
  98. package/dist/features/admin/components/AdminProductsView.d.ts +4 -4
  99. package/dist/features/admin/components/AdminProductsView.js +167 -163
  100. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +1 -1
  101. package/dist/features/admin/components/AdminReturnRequestsView.js +64 -66
  102. package/dist/features/admin/components/AdminReviewsView.d.ts +3 -7
  103. package/dist/features/admin/components/AdminReviewsView.js +94 -110
  104. package/dist/features/admin/components/AdminScammersView.d.ts +2 -3
  105. package/dist/features/admin/components/AdminScammersView.js +53 -97
  106. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  107. package/dist/features/admin/components/AdminSessionsView.d.ts +2 -3
  108. package/dist/features/admin/components/AdminSessionsView.js +62 -89
  109. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +1 -1
  110. package/dist/features/admin/components/AdminStoreAddressesView.js +39 -53
  111. package/dist/features/admin/components/AdminStoreEditorView.js +21 -8
  112. package/dist/features/admin/components/AdminStoresView.d.ts +2 -3
  113. package/dist/features/admin/components/AdminStoresView.js +67 -99
  114. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +1 -1
  115. package/dist/features/admin/components/AdminSublistingCategoriesView.js +28 -44
  116. package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +10 -1
  117. package/dist/features/admin/components/AdminSupportTicketDetailView.js +191 -5
  118. package/dist/features/admin/components/AdminSupportTicketsView.d.ts +2 -3
  119. package/dist/features/admin/components/AdminSupportTicketsView.js +65 -96
  120. package/dist/features/admin/components/AdminTeamView.d.ts +2 -2
  121. package/dist/features/admin/components/AdminTeamView.js +40 -74
  122. package/dist/features/admin/components/AdminUserEditorView.d.ts +11 -1
  123. package/dist/features/admin/components/AdminUserEditorView.js +80 -6
  124. package/dist/features/admin/components/AdminUsersView.d.ts +2 -3
  125. package/dist/features/admin/components/AdminUsersView.js +108 -100
  126. package/dist/features/admin/components/AdminViewCards.d.ts +1 -1
  127. package/dist/features/admin/components/AdminWishlistsView.d.ts +2 -3
  128. package/dist/features/admin/components/AdminWishlistsView.js +36 -62
  129. package/dist/features/admin/components/DataListingView.d.ts +122 -0
  130. package/dist/features/admin/components/DataListingView.js +66 -0
  131. package/dist/features/admin/components/index.d.ts +10 -4
  132. package/dist/features/admin/components/index.js +6 -2
  133. package/dist/features/admin/constants/filter-tabs.d.ts +23 -17
  134. package/dist/features/admin/constants/filter-tabs.js +21 -17
  135. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -0
  136. package/dist/features/admin/hooks/useAdminListing.js +1 -1
  137. package/dist/features/admin/schemas/firestore.js +6 -7
  138. package/dist/features/auctions/server.d.ts +0 -1
  139. package/dist/features/auctions/server.js +0 -1
  140. package/dist/features/auth/actions/realtime-token-actions.js +1 -1
  141. package/dist/features/auth/repository/user.repository.js +1 -1
  142. package/dist/features/cart/repository/cart.repository.d.ts +4 -1
  143. package/dist/features/cart/repository/cart.repository.js +12 -0
  144. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -2
  145. package/dist/features/checkout/index.d.ts +1 -1
  146. package/dist/features/events/components/AdminEventsView.d.ts +3 -3
  147. package/dist/features/events/components/AdminEventsView.js +50 -86
  148. package/dist/features/events/components/EventOfferCard.d.ts +19 -0
  149. package/dist/features/events/components/EventOfferCard.js +29 -0
  150. package/dist/features/events/components/EventRaffleEntryForm.d.ts +25 -0
  151. package/dist/features/events/components/EventRaffleEntryForm.js +37 -0
  152. package/dist/features/events/components/EventRafflesSection.d.ts +1 -4
  153. package/dist/features/events/components/EventRafflesSection.js +17 -6
  154. package/dist/features/events/components/EventSaleBanner.d.ts +21 -0
  155. package/dist/features/events/components/EventSaleBanner.js +18 -0
  156. package/dist/features/events/components/index.d.ts +6 -0
  157. package/dist/features/events/components/index.js +4 -0
  158. package/dist/features/events/repository/event-entry.repository.d.ts +5 -0
  159. package/dist/features/events/repository/event-entry.repository.js +7 -0
  160. package/dist/features/filters/AsyncFacetSection.d.ts +1 -1
  161. package/dist/features/homepage/components/FAQSection.d.ts +0 -5
  162. package/dist/features/homepage/lib/live-stats.js +1 -1
  163. package/dist/features/homepage/schemas/firestore.d.ts +0 -2
  164. package/dist/features/layout/index.d.ts +0 -2
  165. package/dist/features/layout/index.js +0 -1
  166. package/dist/features/pre-orders/server.d.ts +0 -1
  167. package/dist/features/pre-orders/server.js +0 -1
  168. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  169. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  170. package/dist/features/products/components/PrizeDrawsSection.d.ts +1 -4
  171. package/dist/features/products/components/PrizeDrawsSection.js +17 -6
  172. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  173. package/dist/features/products/components/ProductCardMetadataSection.d.ts +11 -0
  174. package/dist/features/products/components/ProductCardMetadataSection.js +25 -0
  175. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  176. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  177. package/dist/features/products/components/ProductGradingTab.d.ts +13 -0
  178. package/dist/features/products/components/ProductGradingTab.js +25 -0
  179. package/dist/features/products/components/ProductGrid.js +14 -2
  180. package/dist/features/products/components/ProductTabsShell.d.ts +5 -1
  181. package/dist/features/products/components/ProductTabsShell.js +6 -1
  182. package/dist/features/products/components/index.d.ts +4 -0
  183. package/dist/features/products/components/index.js +3 -0
  184. package/dist/features/products/constants/action-defs.d.ts +5 -0
  185. package/dist/features/products/constants/action-defs.js +52 -32
  186. package/dist/features/products/constants/sieve.d.ts +24 -4
  187. package/dist/features/products/constants/sieve.js +20 -11
  188. package/dist/features/products/schemas/firestore.d.ts +17 -0
  189. package/dist/features/products/schemas/product-features.validators.d.ts +2 -2
  190. package/dist/features/products/schemas/product-templates.d.ts +2 -4
  191. package/dist/features/products/types/index.d.ts +4 -0
  192. package/dist/features/promotions/server.d.ts +0 -1
  193. package/dist/features/promotions/server.js +0 -1
  194. package/dist/features/search/api/route.js +44 -1
  195. package/dist/features/search/components/Search.js +2 -0
  196. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  197. package/dist/features/search/hooks/useNavSuggestions.js +31 -4
  198. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  199. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  200. package/dist/features/seller/components/SellerAddressesView.js +1 -1
  201. package/dist/features/seller/components/SellerAuctionsView.d.ts +3 -3
  202. package/dist/features/seller/components/SellerAuctionsView.js +60 -90
  203. package/dist/features/seller/components/SellerBidsView.js +1 -1
  204. package/dist/features/seller/components/SellerBundlesView.js +64 -89
  205. package/dist/features/seller/components/SellerClassifiedView.js +67 -90
  206. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  207. package/dist/features/seller/components/SellerCouponsView.d.ts +2 -2
  208. package/dist/features/seller/components/SellerCouponsView.js +45 -84
  209. package/dist/features/seller/components/SellerDigitalCodesView.js +63 -88
  210. package/dist/features/seller/components/SellerGroupedListingsView.js +33 -49
  211. package/dist/features/seller/components/SellerLiveView.js +63 -84
  212. package/dist/features/seller/components/SellerOffersPanel.js +1 -1
  213. package/dist/features/seller/components/SellerOffersView.d.ts +2 -2
  214. package/dist/features/seller/components/SellerOffersView.js +37 -69
  215. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -2
  216. package/dist/features/seller/components/SellerOrdersView.js +4 -4
  217. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  218. package/dist/features/seller/components/SellerPayoutsView.d.ts +2 -2
  219. package/dist/features/seller/components/SellerPayoutsView.js +34 -68
  220. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -2
  221. package/dist/features/seller/components/SellerPreOrdersView.js +49 -82
  222. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -2
  223. package/dist/features/seller/components/SellerPrizeDrawsView.js +49 -82
  224. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  225. package/dist/features/seller/components/SellerProductsView.d.ts +2 -2
  226. package/dist/features/seller/components/SellerProductsView.js +15 -10
  227. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -1
  228. package/dist/features/seller/components/SellerSidebar.d.ts +0 -4
  229. package/dist/features/seller/components/SellerSidebar.js +0 -2
  230. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  231. package/dist/features/seller/components/SellerTemplatesView.js +2 -2
  232. package/dist/features/seller/components/SellersListView.d.ts +1 -2
  233. package/dist/features/seller/components/analytics/SellerAnalyticsStats.d.ts +5 -0
  234. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +2 -8
  235. package/dist/features/seller/components/index.d.ts +0 -3
  236. package/dist/features/seller/components/index.js +0 -2
  237. package/dist/features/seller/server.d.ts +0 -1
  238. package/dist/features/seller/server.js +0 -1
  239. package/dist/features/shell/FormShell.d.ts +1 -1
  240. package/dist/features/shell/FormShell.js +4 -1
  241. package/dist/features/shell/field-groups/ImageFieldGroup.d.ts +18 -0
  242. package/dist/features/shell/field-groups/ImageFieldGroup.js +15 -0
  243. package/dist/features/shell/field-groups/SeoFieldGroup.d.ts +22 -0
  244. package/dist/features/shell/field-groups/SeoFieldGroup.js +16 -0
  245. package/dist/features/shell/field-groups/StatusFieldGroup.d.ts +35 -0
  246. package/dist/features/shell/field-groups/StatusFieldGroup.js +16 -0
  247. package/dist/features/shell/field-groups/TitleDescriptionGroup.d.ts +40 -0
  248. package/dist/features/shell/field-groups/TitleDescriptionGroup.js +16 -0
  249. package/dist/features/shell/field-groups/index.d.ts +13 -0
  250. package/dist/features/shell/field-groups/index.js +9 -0
  251. package/dist/features/shell/index.d.ts +2 -0
  252. package/dist/features/shell/index.js +1 -0
  253. package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +1 -2
  254. package/dist/features/stores/components/StoreFinanceGuideView.d.ts +1 -2
  255. package/dist/features/stores/components/StoreHeader.js +2 -1
  256. package/dist/features/stores/components/StoreListingsGuideView.d.ts +1 -2
  257. package/dist/features/stores/components/StoreOrdersGuideView.d.ts +1 -2
  258. package/dist/features/stores/components/StoreScopedSearch.d.ts +16 -0
  259. package/dist/features/stores/components/StoreScopedSearch.js +27 -0
  260. package/dist/features/stores/components/StoreSettingsGuideView.d.ts +1 -2
  261. package/dist/features/stores/server.d.ts +0 -1
  262. package/dist/features/stores/server.js +0 -1
  263. package/dist/features/support/schemas/firestore.d.ts +22 -1
  264. package/dist/features/support/schemas/firestore.js +10 -0
  265. package/dist/features/wishlist/server.d.ts +0 -1
  266. package/dist/features/wishlist/server.js +0 -1
  267. package/dist/index.d.ts +9 -27
  268. package/dist/index.js +14 -50
  269. package/dist/next/routing/route-map.d.ts +8 -0
  270. package/dist/next/routing/route-map.js +4 -0
  271. package/dist/react/hooks/useListingTypeFlags.d.ts +32 -0
  272. package/dist/react/hooks/useListingTypeFlags.js +19 -0
  273. package/dist/security/index.d.ts +1 -1
  274. package/dist/security/index.js +1 -1
  275. package/dist/security/pii-redact.d.ts +8 -0
  276. package/dist/security/pii-redact.js +10 -1
  277. package/dist/seed/grouped-listings-seed-data.d.ts +4 -0
  278. package/dist/seed/products-preorders-seed-data.d.ts +4 -0
  279. package/dist/seed/products-prize-draws-seed-data.js +3 -0
  280. package/dist/seed/site-settings-seed-data.js +5 -5
  281. package/dist/seed/sub-listings-seed-data.d.ts +4 -0
  282. package/dist/server.d.ts +2 -0
  283. package/dist/server.js +4 -0
  284. package/dist/styles.css +54 -395
  285. package/dist/tailwind-utilities.css +1 -1
  286. package/dist/ui/components/BaseListingCard.d.ts +10 -0
  287. package/dist/ui/components/BaseListingCard.js +17 -1
  288. package/dist/ui/components/DetailPageGallery.d.ts +32 -0
  289. package/dist/ui/components/DetailPageGallery.js +47 -0
  290. package/dist/ui/components/DetailPageHero.d.ts +30 -0
  291. package/dist/ui/components/DetailPageHero.js +22 -0
  292. package/dist/ui/components/DetailPageTabs.d.ts +34 -0
  293. package/dist/ui/components/DetailPageTabs.js +38 -0
  294. package/dist/ui/components/HorizontalScroller.style.css +15 -2
  295. package/dist/ui/components/ListingLayout.d.ts +11 -2
  296. package/dist/ui/components/ListingLayout.js +12 -6
  297. package/dist/ui/components/PaginatedSelect.d.ts +66 -0
  298. package/dist/ui/components/PaginatedSelect.js +201 -0
  299. package/dist/ui/components/PaginatedSelect.style.css +254 -0
  300. package/dist/ui/components/Semantic.d.ts +0 -4
  301. package/dist/ui/components/Semantic.js +0 -2
  302. package/dist/ui/components/SettingsSection.d.ts +47 -0
  303. package/dist/ui/components/SettingsSection.js +38 -0
  304. package/dist/ui/components/index.style.css +1 -4
  305. package/dist/ui/index.d.ts +12 -14
  306. package/dist/ui/index.js +6 -7
  307. package/dist/utils/id-generators.d.ts +1 -18
  308. package/dist/utils/id-generators.js +51 -18
  309. package/dist/validation/schemas.d.ts +25 -0
  310. package/dist/validation/schemas.js +28 -0
  311. package/package.json +1 -1
@@ -9,7 +9,26 @@
9
9
  * Client — useAuthGate() shows LoginRequiredModal for Tier 1 (public) actions
10
10
  * Server — checkActionAllowed() enforces the same guards on every server action
11
11
  * Admin — ActionPermissionsManager toggles defaultEnabled via siteSettings.actionConfig
12
+ *
13
+ * Label source of truth: `ACTIONS.{RESOURCE}["..."].label` in
14
+ * _internal/shared/actions/action-registry.ts. `ACTION_META` derives its labels
15
+ * via `regLabel()` where a registry counterpart exists; entries with no
16
+ * counterpart keep an inline literal until a registry leaf is added (W1-5).
17
+ */
18
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
19
+ // ─────────────────────────────────────────────────────────────────────────────
20
+ // Label-from-registry helper (W1-5)
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ /**
23
+ * Returns the label for `ACTIONS[resource][id]`. The `fallback` is used only
24
+ * when the registry has no leaf yet — orphan IDs should be added to ACTIONS
25
+ * over time. Adding the fallback parameter as required ensures every call
26
+ * site documents what the inline label was at migration time, simplifying
27
+ * the eventual cleanup.
12
28
  */
29
+ function regLabel(resource, id, fallback) {
30
+ return ACTIONS[resource]?.[id]?.label ?? fallback;
31
+ }
13
32
  // ─────────────────────────────────────────────────────────────────────────────
14
33
  // § 1 Product / listing actions
15
34
  // Used by: detail pages, BulkActionsBar, BuyBar
@@ -64,49 +83,50 @@ export const ACTION_ID = {
64
83
  DELETE_ACCOUNT: "delete-account",
65
84
  };
66
85
  export const ACTION_META = {
67
- [ACTION_ID.BUY_NOW]: { id: ACTION_ID.BUY_NOW, label: "Buy Now", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
68
- [ACTION_ID.ADD_TO_CART]: { id: ACTION_ID.ADD_TO_CART, label: "Add to Cart", variant: "secondary", iconName: "ShoppingCart" },
69
- [ACTION_ID.ADD_TO_WISHLIST]: { id: ACTION_ID.ADD_TO_WISHLIST, label: "Add to Wishlist", variant: "ghost", iconName: "Heart", requiresAuth: true, authMessage: "You need to be signed in to save items to your wishlist." },
70
- [ACTION_ID.REMOVE_FROM_WISHLIST]: { id: ACTION_ID.REMOVE_FROM_WISHLIST, label: "Remove from Wishlist", variant: "ghost", iconName: "HeartOff", requiresAuth: true, authMessage: "You need to be signed in to manage your wishlist." },
71
- [ACTION_ID.MAKE_OFFER]: { id: ACTION_ID.MAKE_OFFER, label: "Make an Offer", variant: "outline", iconName: "Tag", requiresAuth: true, authMessage: "You need to be signed in to make an offer." },
72
- [ACTION_ID.SHARE]: { id: ACTION_ID.SHARE, label: "Share", variant: "ghost", iconName: "Share2" },
73
- [ACTION_ID.COMPARE]: { id: ACTION_ID.COMPARE, label: "Compare", variant: "secondary", iconName: "Columns" },
74
- [ACTION_ID.PLACE_BID]: { id: ACTION_ID.PLACE_BID, label: "Place Bid", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to place a bid." },
75
- [ACTION_ID.BUY_NOW_AUCTION]: { id: ACTION_ID.BUY_NOW_AUCTION, label: "Buy Now", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
76
- [ACTION_ID.WATCH_AUCTION]: { id: ACTION_ID.WATCH_AUCTION, label: "Watch", variant: "ghost", iconName: "Eye", requiresAuth: true, authMessage: "You need to be signed in to watch auctions." },
77
- [ACTION_ID.UNWATCH_AUCTION]: { id: ACTION_ID.UNWATCH_AUCTION, label: "Unwatch", variant: "ghost", iconName: "EyeOff", requiresAuth: true, authMessage: "You need to be signed in to manage your watchlist." },
78
- [ACTION_ID.RESERVE_NOW]: { id: ACTION_ID.RESERVE_NOW, label: "Reserve Now", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to reserve a pre-order." },
79
- [ACTION_ID.CANCEL_RESERVATION]: { id: ACTION_ID.CANCEL_RESERVATION, label: "Cancel Reservation", variant: "danger", iconName: "X", requiresAuth: true, authMessage: "You need to be signed in to cancel a reservation." },
86
+ [ACTION_ID.BUY_NOW]: { id: ACTION_ID.BUY_NOW, label: regLabel("PRODUCT", "buy-now", "Buy Now"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
87
+ [ACTION_ID.ADD_TO_CART]: { id: ACTION_ID.ADD_TO_CART, label: regLabel("PRODUCT", "add-to-cart", "Add to Cart"), variant: "secondary", iconName: "ShoppingCart" },
88
+ [ACTION_ID.ADD_TO_WISHLIST]: { id: ACTION_ID.ADD_TO_WISHLIST, label: regLabel("PRODUCT", "add-to-wishlist", "Add to Wishlist"), variant: "ghost", iconName: "Heart", requiresAuth: true, authMessage: "You need to be signed in to save items to your wishlist." },
89
+ [ACTION_ID.REMOVE_FROM_WISHLIST]: { id: ACTION_ID.REMOVE_FROM_WISHLIST, label: regLabel("PRODUCT", "remove-from-wishlist", "Remove from Wishlist"), variant: "ghost", iconName: "HeartOff", requiresAuth: true, authMessage: "You need to be signed in to manage your wishlist." },
90
+ [ACTION_ID.MAKE_OFFER]: { id: ACTION_ID.MAKE_OFFER, label: regLabel("PRODUCT", "make-offer", "Make an Offer"), variant: "outline", iconName: "Tag", requiresAuth: true, authMessage: "You need to be signed in to make an offer." },
91
+ [ACTION_ID.SHARE]: { id: ACTION_ID.SHARE, label: regLabel("PRODUCT", "share", "Share"), variant: "ghost", iconName: "Share2" },
92
+ [ACTION_ID.COMPARE]: { id: ACTION_ID.COMPARE, label: regLabel("PRODUCT", "compare", "Compare"), variant: "secondary", iconName: "Columns" },
93
+ [ACTION_ID.PLACE_BID]: { id: ACTION_ID.PLACE_BID, label: regLabel("AUCTION", "place-bid", "Place Bid"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to place a bid." },
94
+ [ACTION_ID.BUY_NOW_AUCTION]: { id: ACTION_ID.BUY_NOW_AUCTION, label: regLabel("AUCTION", "buy-it-now", "Buy Now"), variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
95
+ [ACTION_ID.WATCH_AUCTION]: { id: ACTION_ID.WATCH_AUCTION, label: regLabel("AUCTION", "watch", "Watch"), variant: "ghost", iconName: "Eye", requiresAuth: true, authMessage: "You need to be signed in to watch auctions." },
96
+ [ACTION_ID.UNWATCH_AUCTION]: { id: ACTION_ID.UNWATCH_AUCTION, label: regLabel("AUCTION", "unwatch", "Unwatch"), variant: "ghost", iconName: "EyeOff", requiresAuth: true, authMessage: "You need to be signed in to manage your watchlist." },
97
+ [ACTION_ID.RESERVE_NOW]: { id: ACTION_ID.RESERVE_NOW, label: regLabel("PRE_ORDER", "reserve-now", "Reserve Now"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to reserve a pre-order." },
98
+ [ACTION_ID.CANCEL_RESERVATION]: { id: ACTION_ID.CANCEL_RESERVATION, label: regLabel("PRE_ORDER", "cancel-reservation", "Cancel Reservation"), variant: "danger", iconName: "X", requiresAuth: true, authMessage: "You need to be signed in to cancel a reservation." },
80
99
  // ── Checkout / navigation CTAs ────────────────────────────────────────────
81
- [ACTION_ID.CHECKOUT]: { id: ACTION_ID.CHECKOUT, label: "Checkout", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
82
- [ACTION_ID.CONTINUE_TO_VERIFY]: { id: ACTION_ID.CONTINUE_TO_VERIFY, label: "Continue", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
83
- [ACTION_ID.SEND_OTP]: { id: ACTION_ID.SEND_OTP, label: "Send Code", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
84
- [ACTION_ID.VERIFY_OTP]: { id: ACTION_ID.VERIFY_OTP, label: "Verify & Continue", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
85
- [ACTION_ID.PAY_ONLINE]: { id: ACTION_ID.PAY_ONLINE, label: "Pay Online", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
86
- [ACTION_ID.PAY_COD]: { id: ACTION_ID.PAY_COD, label: "Cash on Delivery", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
87
- [ACTION_ID.APPLY_COUPON]: { id: ACTION_ID.APPLY_COUPON, label: "Apply", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to apply a coupon." },
88
- [ACTION_ID.REMOVE_COUPON]: { id: ACTION_ID.REMOVE_COUPON, label: "Remove", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to manage coupons." },
89
- [ACTION_ID.ENTER_PRIZE_DRAW]: { id: ACTION_ID.ENTER_PRIZE_DRAW, label: "Enter Draw", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a prize draw." },
100
+ [ACTION_ID.CHECKOUT]: { id: ACTION_ID.CHECKOUT, label: regLabel("CART", "checkout", "Checkout"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
101
+ [ACTION_ID.CONTINUE_TO_VERIFY]: { id: ACTION_ID.CONTINUE_TO_VERIFY, label: regLabel("CHECKOUT", "continue-to-verification", "Continue"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
102
+ [ACTION_ID.SEND_OTP]: { id: ACTION_ID.SEND_OTP, label: regLabel("CHECKOUT", "send-otp", "Send Code"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
103
+ [ACTION_ID.VERIFY_OTP]: { id: ACTION_ID.VERIFY_OTP, label: regLabel("CHECKOUT", "verify-otp", "Verify & Continue"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
104
+ [ACTION_ID.PAY_ONLINE]: { id: ACTION_ID.PAY_ONLINE, label: regLabel("CHECKOUT", "pay-online", "Pay Online"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
105
+ [ACTION_ID.PAY_COD]: { id: ACTION_ID.PAY_COD, label: regLabel("CHECKOUT", "pay-cod", "Cash on Delivery"), variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
106
+ [ACTION_ID.APPLY_COUPON]: { id: ACTION_ID.APPLY_COUPON, label: regLabel("CHECKOUT", "apply-coupon", "Apply"), variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to apply a coupon." },
107
+ [ACTION_ID.REMOVE_COUPON]: { id: ACTION_ID.REMOVE_COUPON, label: regLabel("CHECKOUT", "remove-coupon", "Remove"), variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to manage coupons." },
108
+ [ACTION_ID.ENTER_PRIZE_DRAW]: { id: ACTION_ID.ENTER_PRIZE_DRAW, label: regLabel("PRIZE_DRAW", "enter-draw", "Enter Draw"), variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a prize draw." },
109
+ // ── Inline literals: no registry counterpart yet (orphan IDs — add to ACTIONS in a follow-up sweep) ─
90
110
  [ACTION_ID.ENTER_RAFFLE]: { id: ACTION_ID.ENTER_RAFFLE, label: "Enter Raffle", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a raffle." },
91
111
  [ACTION_ID.REPORT_LISTING]: { id: ACTION_ID.REPORT_LISTING, label: "Report Listing", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to report a listing." },
92
- [ACTION_ID.FOLLOW_STORE]: { id: ACTION_ID.FOLLOW_STORE, label: "Follow Store", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to follow a store." },
112
+ [ACTION_ID.FOLLOW_STORE]: { id: ACTION_ID.FOLLOW_STORE, label: regLabel("STORE", "follow", "Follow Store"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to follow a store." },
93
113
  // ── Reviews & social ──────────────────────────────────────────────────────
94
- [ACTION_ID.WRITE_REVIEW]: { id: ACTION_ID.WRITE_REVIEW, label: "Write a Review", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to write a review." },
114
+ [ACTION_ID.WRITE_REVIEW]: { id: ACTION_ID.WRITE_REVIEW, label: regLabel("USER", "write-review", "Write a Review"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to write a review." },
95
115
  [ACTION_ID.MESSAGE_SELLER]: { id: ACTION_ID.MESSAGE_SELLER, label: "Message Seller", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to message a seller." },
96
116
  // ── Seller CTAs ───────────────────────────────────────────────────────────
97
117
  [ACTION_ID.BECOME_SELLER]: { id: ACTION_ID.BECOME_SELLER, label: "Apply as Seller", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to apply as a seller." },
98
- [ACTION_ID.REQUEST_PAYOUT]: { id: ACTION_ID.REQUEST_PAYOUT, label: "Request Payout", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a payout.", requiredPermission: "seller.payouts.request" },
99
- [ACTION_ID.RESPOND_TO_REVIEW]: { id: ACTION_ID.RESPOND_TO_REVIEW, label: "Respond to Review", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to respond to a review.", requiredPermission: "seller.reviews.respond" },
118
+ [ACTION_ID.REQUEST_PAYOUT]: { id: ACTION_ID.REQUEST_PAYOUT, label: regLabel("STORE", "request-payout", "Request Payout"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a payout.", requiredPermission: "seller.payouts.request" },
119
+ [ACTION_ID.RESPOND_TO_REVIEW]: { id: ACTION_ID.RESPOND_TO_REVIEW, label: regLabel("STORE", "reply-review", "Respond to Review"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to respond to a review.", requiredPermission: "seller.reviews.respond" },
100
120
  // ── User account actions ──────────────────────────────────────────────────
101
- [ACTION_ID.CANCEL_ORDER]: { id: ACTION_ID.CANCEL_ORDER, label: "Cancel Order", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to cancel an order." },
102
- [ACTION_ID.REQUEST_RETURN]: { id: ACTION_ID.REQUEST_RETURN, label: "Request Return", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a return." },
103
- [ACTION_ID.REORDER]: { id: ACTION_ID.REORDER, label: "Reorder", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to reorder." },
104
- [ACTION_ID.TRACK_ORDER]: { id: ACTION_ID.TRACK_ORDER, label: "Track Order", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to track your order." },
121
+ [ACTION_ID.CANCEL_ORDER]: { id: ACTION_ID.CANCEL_ORDER, label: regLabel("USER", "cancel-order", "Cancel Order"), variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to cancel an order." },
122
+ [ACTION_ID.REQUEST_RETURN]: { id: ACTION_ID.REQUEST_RETURN, label: regLabel("USER", "request-return", "Request Return"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a return." },
123
+ [ACTION_ID.REORDER]: { id: ACTION_ID.REORDER, label: regLabel("USER", "reorder", "Reorder"), variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to reorder." },
124
+ [ACTION_ID.TRACK_ORDER]: { id: ACTION_ID.TRACK_ORDER, label: regLabel("USER", "track-order", "Track Order"), variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to track your order." },
105
125
  [ACTION_ID.EDIT_PROFILE]: { id: ACTION_ID.EDIT_PROFILE, label: "Edit Profile", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to edit your profile." },
106
126
  [ACTION_ID.ADD_ADDRESS]: { id: ACTION_ID.ADD_ADDRESS, label: "Add Address", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to add an address." },
107
127
  [ACTION_ID.EDIT_ADDRESS]: { id: ACTION_ID.EDIT_ADDRESS, label: "Edit Address", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to edit an address." },
108
- [ACTION_ID.DELETE_ADDRESS]: { id: ACTION_ID.DELETE_ADDRESS, label: "Delete Address", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to delete an address." },
109
- [ACTION_ID.CHANGE_PASSWORD]: { id: ACTION_ID.CHANGE_PASSWORD, label: "Change Password", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to change your password." },
128
+ [ACTION_ID.DELETE_ADDRESS]: { id: ACTION_ID.DELETE_ADDRESS, label: regLabel("USER", "delete-address", "Delete Address"), variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to delete an address." },
129
+ [ACTION_ID.CHANGE_PASSWORD]: { id: ACTION_ID.CHANGE_PASSWORD, label: regLabel("USER", "update-password", "Change Password"), variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to change your password." },
110
130
  [ACTION_ID.DELETE_ACCOUNT]: { id: ACTION_ID.DELETE_ACCOUNT, label: "Delete Account", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to delete your account.", requiredPermission: "user.account.delete" },
111
131
  };
112
132
  // Detail page action groups — ordered top-to-bottom in the right-hand panel
@@ -2,6 +2,20 @@ export type SortOption = {
2
2
  readonly value: string;
3
3
  readonly label: string;
4
4
  };
5
+ /** Time + price sorts, the common subset across most listing-type pickers. */
6
+ export declare const BASE_SORT_OPTIONS: readonly [{
7
+ readonly value: string;
8
+ readonly label: "Newest First";
9
+ }, {
10
+ readonly value: string;
11
+ readonly label: "Oldest First";
12
+ }, {
13
+ readonly value: string;
14
+ readonly label: "Price: Low to High";
15
+ }, {
16
+ readonly value: string;
17
+ readonly label: "Price: High to Low";
18
+ }];
5
19
  export declare const STANDARD_SORT_OPTIONS: readonly [{
6
20
  readonly value: string;
7
21
  readonly label: "Newest First";
@@ -108,10 +122,13 @@ export declare const PREORDER_SORT_OPTIONS: readonly [{
108
122
  }, {
109
123
  readonly value: string;
110
124
  readonly label: "Latest Delivery";
111
- }, {
125
+ }, ...({
112
126
  readonly value: string;
113
127
  readonly label: "Newest First";
114
- }, {
128
+ } | {
129
+ readonly value: string;
130
+ readonly label: "Oldest First";
131
+ })[], {
115
132
  readonly value: string;
116
133
  readonly label: "Price: Low to High";
117
134
  }, {
@@ -124,10 +141,13 @@ export declare const PREORDER_SORT_OPTIONS: readonly [{
124
141
  readonly value: string;
125
142
  readonly label: "Lowest Deposit First";
126
143
  }];
127
- export declare const BUNDLE_SORT_OPTIONS: readonly [{
144
+ export declare const BUNDLE_SORT_OPTIONS: readonly [...({
128
145
  readonly value: string;
129
146
  readonly label: "Newest First";
130
- }, {
147
+ } | {
148
+ readonly value: string;
149
+ readonly label: "Oldest First";
150
+ })[], {
131
151
  readonly value: string;
132
152
  readonly label: "Price: Low to High";
133
153
  }, {
@@ -5,13 +5,25 @@ const LABEL_PRICE_LOW = "Price: Low to High";
5
5
  const LABEL_NEWEST = "Newest First";
6
6
  const LABEL_OLDEST = "Oldest First";
7
7
  // ---------------------------------------------------------------------------
8
- // Standard Products
8
+ // W2-6 — Base sort options shared by standard / pre-order / bundle / prize-draw.
9
+ // Auctions get their own base (auctionEndDate primary) because the "Ending Soon"
10
+ // dimension dominates browse intent.
9
11
  // ---------------------------------------------------------------------------
10
- export const STANDARD_SORT_OPTIONS = [
12
+ const BASE_TIME_SORTS = [
11
13
  { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: LABEL_NEWEST },
12
14
  { value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: LABEL_OLDEST },
15
+ ];
16
+ const BASE_PRICE_SORTS = [
13
17
  { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: LABEL_PRICE_LOW },
14
18
  { value: sortBy(PRODUCT_FIELDS.PRICE), label: LABEL_PRICE_HIGH },
19
+ ];
20
+ /** Time + price sorts, the common subset across most listing-type pickers. */
21
+ export const BASE_SORT_OPTIONS = [...BASE_TIME_SORTS, ...BASE_PRICE_SORTS];
22
+ // ---------------------------------------------------------------------------
23
+ // Standard Products
24
+ // ---------------------------------------------------------------------------
25
+ export const STANDARD_SORT_OPTIONS = [
26
+ ...BASE_SORT_OPTIONS,
15
27
  { value: sortBy(PRODUCT_FIELDS.TITLE, "ASC"), label: "Name: A–Z" },
16
28
  { value: sortBy(PRODUCT_FIELDS.TITLE), label: "Name: Z–A" },
17
29
  { value: sortBy(PRODUCT_FIELDS.FEATURED), label: "Featured First" },
@@ -29,7 +41,7 @@ export const STANDARD_PUBLIC_SORT_OPTIONS = [
29
41
  STANDARD_SORT_OPTIONS[9],
30
42
  ];
31
43
  // ---------------------------------------------------------------------------
32
- // Auctions
44
+ // Auctions — auction-specific base puts auctionEndDate primary
33
45
  // ---------------------------------------------------------------------------
34
46
  export const AUCTION_SORT_OPTIONS = [
35
47
  { value: sortBy(PRODUCT_FIELDS.AUCTION_END_DATE, "ASC"), label: "Ending Soon" },
@@ -56,9 +68,8 @@ export const AUCTION_PUBLIC_SORT_OPTIONS = [
56
68
  export const PREORDER_SORT_OPTIONS = [
57
69
  { value: sortBy(PRODUCT_FIELDS.PRE_ORDER_DELIVERY_DATE, "ASC"), label: "Earliest Delivery" },
58
70
  { value: sortBy(PRODUCT_FIELDS.PRE_ORDER_DELIVERY_DATE), label: "Latest Delivery" },
59
- { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: LABEL_NEWEST },
60
- { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: LABEL_PRICE_LOW },
61
- { value: sortBy(PRODUCT_FIELDS.PRICE), label: LABEL_PRICE_HIGH },
71
+ ...BASE_TIME_SORTS.slice(0, 1), // Newest First
72
+ ...BASE_PRICE_SORTS,
62
73
  { value: sortBy(PRODUCT_FIELDS.PRE_ORDER_CURRENT_COUNT), label: "Fewest Slots Left" },
63
74
  { value: sortBy(PRODUCT_FIELDS.PRE_ORDER_DEPOSIT_AMOUNT, "ASC"), label: "Lowest Deposit First" },
64
75
  ];
@@ -66,9 +77,8 @@ export const PREORDER_SORT_OPTIONS = [
66
77
  // Bundles
67
78
  // ---------------------------------------------------------------------------
68
79
  export const BUNDLE_SORT_OPTIONS = [
69
- { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: LABEL_NEWEST },
70
- { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: LABEL_PRICE_LOW },
71
- { value: sortBy(PRODUCT_FIELDS.PRICE), label: LABEL_PRICE_HIGH },
80
+ ...BASE_TIME_SORTS.slice(0, 1), // Newest First
81
+ ...BASE_PRICE_SORTS,
72
82
  { value: "-savingsAmount", label: "Most Savings" },
73
83
  { value: "-bundleItemCount", label: "Most Items" },
74
84
  ];
@@ -76,8 +86,7 @@ export const BUNDLE_SORT_OPTIONS = [
76
86
  // Prize Draws
77
87
  // ---------------------------------------------------------------------------
78
88
  export const PRIZE_DRAW_SORT_OPTIONS = [
79
- { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: LABEL_NEWEST },
80
- { value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: LABEL_OLDEST },
89
+ ...BASE_TIME_SORTS,
81
90
  { value: sortBy(PRODUCT_FIELDS.PRIZE_REVEAL_WINDOW_START, "ASC"), label: "Reveal: Soonest" },
82
91
  { value: sortBy(PRODUCT_FIELDS.PRIZE_REVEAL_WINDOW_START), label: "Reveal: Furthest" },
83
92
  { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Entry: Low to High" },
@@ -132,6 +132,10 @@ export interface ProductDocument {
132
132
  status: ProductStatus;
133
133
  storeId: string;
134
134
  storeName?: string;
135
+ /** W1-34 — denormalized seller rating (0–5) shown on product detail store card. */
136
+ storeRating?: number;
137
+ /** W1-34 — denormalized seller total review count shown alongside the rating. */
138
+ storeReviewCount?: number;
135
139
  featured: boolean;
136
140
  tags: string[];
137
141
  specifications?: ProductSpecification[];
@@ -194,6 +198,19 @@ export interface ProductDocument {
194
198
  groupParentSlug?: string;
195
199
  groupChildSlugs?: string[];
196
200
  groupTitle?: string;
201
+ /**
202
+ * W1-45 — optional icon shown as an overlay badge on every card whose
203
+ * product belongs to this group. Set once on the group parent; cards
204
+ * inherit it via the snapshot pipeline. Either an emoji or a media slug
205
+ * (rendered via `/media/<slug>`).
206
+ */
207
+ groupIcon?: string;
208
+ /**
209
+ * W1-45 — denormalized icon from the sublisting category (`display.icon`).
210
+ * Mirrored onto the product snapshot at create/update time so cards can
211
+ * render it without an extra category lookup per row.
212
+ */
213
+ sublistingIcon?: string;
197
214
  /**
198
215
  * Required since Phase 4 dropped the legacy `isAuction` / `isPreOrder`
199
216
  * booleans. Every product document carries this; queries route through
@@ -89,8 +89,8 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
89
89
  label?: string | undefined;
90
90
  icon?: string | undefined;
91
91
  isActive?: boolean | undefined;
92
- iconColor?: string | undefined;
93
92
  displayOrder?: number | undefined;
93
+ iconColor?: string | undefined;
94
94
  productTypes?: ("auction" | "prize-draw" | "classified" | "digital-code" | "live" | "all" | "product" | "preorder")[] | undefined;
95
95
  }, {
96
96
  category?: "seller" | "custom" | "auction" | "condition" | "shipping" | "preorder" | "platform" | undefined;
@@ -98,8 +98,8 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
98
98
  label?: string | undefined;
99
99
  icon?: string | undefined;
100
100
  isActive?: boolean | undefined;
101
- iconColor?: string | undefined;
102
101
  displayOrder?: number | undefined;
102
+ iconColor?: string | undefined;
103
103
  productTypes?: ("auction" | "prize-draw" | "classified" | "digital-code" | "live" | "all" | "product" | "preorder")[] | undefined;
104
104
  }>;
105
105
  export type ProductFeatureAdminCreatePayload = z.infer<typeof productFeatureAdminCreateSchema>;
@@ -22,7 +22,5 @@ export interface ProductTemplateDocument {
22
22
  createdAt: Date | string;
23
23
  updatedAt: Date | string;
24
24
  }
25
- export interface ProductTemplateCreateInput extends Omit<ProductTemplateDocument, "id" | "createdAt" | "updatedAt"> {
26
- }
27
- export interface ProductTemplateUpdateInput extends Partial<Omit<ProductTemplateDocument, "id" | "storeId" | "createdAt">> {
28
- }
25
+ export type ProductTemplateCreateInput = Omit<ProductTemplateDocument, "id" | "createdAt" | "updatedAt">;
26
+ export type ProductTemplateUpdateInput = Partial<Omit<ProductTemplateDocument, "id" | "storeId" | "createdAt">>;
@@ -65,6 +65,10 @@ export interface ProductItem {
65
65
  groupParentSlug?: string;
66
66
  groupChildSlugs?: string[];
67
67
  groupTitle?: string;
68
+ /** W1-45 — icon shown as a card overlay; emoji or `/media/<slug>`. */
69
+ groupIcon?: string;
70
+ /** W1-45 — denormalized icon from the sublisting category. */
71
+ sublistingIcon?: string;
68
72
  isOnSale?: boolean;
69
73
  isSold?: boolean;
70
74
  inStock?: boolean;
@@ -4,6 +4,5 @@
4
4
  * Server-only entry point for promotions repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { PromotionsRepository } from "./repository/promotions.repository";
8
7
  export { couponsRepository } from "./repository/coupons.repository";
9
8
  export { GET as promotionsGET, GET } from "./api/route";
@@ -4,6 +4,5 @@
4
4
  * Server-only entry point for promotions repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { PromotionsRepository } from "./repository/promotions.repository";
8
7
  export { couponsRepository } from "./repository/coupons.repository";
9
8
  export { GET as promotionsGET, GET } from "./api/route";
@@ -21,6 +21,8 @@
21
21
  import { NextResponse } from "next/server.js";
22
22
  import { getProviders } from "../../../contracts";
23
23
  import { SearchRepository } from "../repository/search.repository";
24
+ import { isListingTypeEnabled, enabledListingTypes, } from "../../../_internal/shared/listing-types/feature-flags";
25
+ import { getSiteSettingsGlobal } from "../../admin/utils/getSiteSettingsGlobal";
24
26
  function param(url, key) {
25
27
  return url.searchParams.get(key);
26
28
  }
@@ -55,6 +57,32 @@ export async function GET(request) {
55
57
  const maxPriceRaw = numParam(url, "maxPrice", 0);
56
58
  const page = numParam(url, "page", 1);
57
59
  const pageSize = Math.min(numParam(url, "pageSize", 20), 100);
60
+ // W1-43 — listing-type feature flag gating. Reject a search scoped to a
61
+ // disabled listing type with an empty result; for unscoped searches,
62
+ // strip disabled types post-query so search-bar suggestions stay clean.
63
+ let siteSettings = null;
64
+ try {
65
+ siteSettings = await getSiteSettingsGlobal();
66
+ }
67
+ catch {
68
+ siteSettings = null;
69
+ }
70
+ if (listingType && siteSettings && !isListingTypeEnabled(listingType, siteSettings)) {
71
+ return NextResponse.json({
72
+ success: true,
73
+ data: {
74
+ items: [],
75
+ total: 0,
76
+ page,
77
+ pageSize,
78
+ totalPages: 0,
79
+ hasMore: false,
80
+ backend: "firestore",
81
+ listingTypeDisabled: true,
82
+ },
83
+ });
84
+ }
85
+ const enabledSet = new Set(siteSettings ? enabledListingTypes(siteSettings) : []);
58
86
  const repo = new SearchRepository(db.getRepository("products"));
59
87
  const result = await repo.search({
60
88
  q: param(url, "q") ?? undefined,
@@ -70,9 +98,24 @@ export async function GET(request) {
70
98
  page,
71
99
  pageSize,
72
100
  });
101
+ // W1-43 — when no specific listingType filter, strip disabled types from
102
+ // the surface. Skipped when all types are enabled or settings failed to load.
103
+ let filteredItems = result.items;
104
+ let filteredTotal = result.total;
105
+ if (!listingType && enabledSet.size > 0 && enabledSet.size < 7) {
106
+ const before = filteredItems.length;
107
+ filteredItems = filteredItems.filter((it) => enabledSet.has(it.listingType ?? "standard"));
108
+ const removed = before - filteredItems.length;
109
+ filteredTotal = Math.max(0, filteredTotal - removed);
110
+ }
73
111
  return NextResponse.json({
74
112
  success: true,
75
- data: { ...result, backend: "firestore" },
113
+ data: {
114
+ ...result,
115
+ items: filteredItems,
116
+ total: filteredTotal,
117
+ backend: "firestore",
118
+ },
76
119
  });
77
120
  }
78
121
  catch (error) {
@@ -12,12 +12,14 @@ const DEFAULT_TYPE_ICONS = {
12
12
  category: "🗂️",
13
13
  blog: "✍️",
14
14
  event: "🎉",
15
+ product: "📦",
15
16
  };
16
17
  const DEFAULT_TYPE_BADGES = {
17
18
  page: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",
18
19
  category: "bg-blue-100 text-blue-600 dark:bg-blue-900/40 dark:text-blue-300",
19
20
  blog: "bg-fuchsia-100 text-fuchsia-600 dark:bg-fuchsia-900/40 dark:text-fuchsia-300",
20
21
  event: "bg-amber-100 text-amber-600 dark:bg-amber-900/40 dark:text-amber-300",
22
+ product: "bg-emerald-100 text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-300",
21
23
  };
22
24
  function SuggestionItem({ suggestion, itemIndex, activeIndex, onSelect, onHover, typeIcons, typeBadges, }) {
23
25
  const isActive = activeIndex === itemIndex;
@@ -1,10 +1,14 @@
1
1
  export interface NavSuggestionRecord {
2
2
  objectID: string;
3
- type: "page" | "category" | "blog" | "event";
3
+ type: "page" | "category" | "blog" | "event" | "product";
4
4
  title: string;
5
5
  subtitle?: string;
6
6
  url: string;
7
7
  }
8
+ /**
9
+ * W1-19 — wired to `/api/search/suggestions` 2026-05-23. Fetches up to 20
10
+ * matches (5 per resource type) and surfaces them as typeahead rows.
11
+ */
8
12
  export declare function useNavSuggestions(query: string, selectedType?: string, debounceMs?: number): {
9
13
  suggestions: NavSuggestionRecord[];
10
14
  isLoading: boolean;
@@ -1,23 +1,48 @@
1
1
  "use client";
2
2
  import { useEffect, useRef, useState } from "react";
3
+ const SUGGESTIONS_ENDPOINT = "/api/search/suggestions";
4
+ /**
5
+ * W1-19 — wired to `/api/search/suggestions` 2026-05-23. Fetches up to 20
6
+ * matches (5 per resource type) and surfaces them as typeahead rows.
7
+ */
3
8
  export function useNavSuggestions(query, selectedType, debounceMs = 250) {
4
9
  const [suggestions, setSuggestions] = useState([]);
5
10
  const [isLoading, setIsLoading] = useState(false);
6
11
  const timerRef = useRef(null);
12
+ const abortRef = useRef(null);
7
13
  useEffect(() => {
8
14
  if (timerRef.current)
9
15
  clearTimeout(timerRef.current);
10
- if (!query.trim()) {
16
+ if (abortRef.current)
17
+ abortRef.current.abort();
18
+ const trimmed = query.trim();
19
+ if (!trimmed) {
11
20
  setSuggestions([]);
21
+ setIsLoading(false);
12
22
  return;
13
23
  }
14
24
  timerRef.current = setTimeout(async () => {
15
25
  setIsLoading(true);
26
+ const ctrl = new AbortController();
27
+ abortRef.current = ctrl;
16
28
  try {
17
- setSuggestions([]);
29
+ const params = new URLSearchParams({ q: trimmed });
30
+ if (selectedType && selectedType !== "all") {
31
+ params.set("type", selectedType);
32
+ }
33
+ const res = await fetch(`${SUGGESTIONS_ENDPOINT}?${params.toString()}`, { signal: ctrl.signal, credentials: "same-origin" });
34
+ if (!res.ok) {
35
+ setSuggestions([]);
36
+ return;
37
+ }
38
+ const body = (await res.json());
39
+ const items = body.data?.suggestions ?? body.suggestions ?? [];
40
+ setSuggestions(items);
18
41
  }
19
- catch {
20
- setSuggestions([]);
42
+ catch (err) {
43
+ if (err.name !== "AbortError") {
44
+ setSuggestions([]);
45
+ }
21
46
  }
22
47
  finally {
23
48
  setIsLoading(false);
@@ -26,6 +51,8 @@ export function useNavSuggestions(query, selectedType, debounceMs = 250) {
26
51
  return () => {
27
52
  if (timerRef.current)
28
53
  clearTimeout(timerRef.current);
54
+ if (abortRef.current)
55
+ abortRef.current.abort();
29
56
  };
30
57
  }, [query, selectedType, debounceMs]);
31
58
  return { suggestions, isLoading };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { InlineCreateSelect } from "../../../ui/components/InlineCreateSelect";
3
+ import { PaginatedSelect } from "../../../ui/components/PaginatedSelect";
4
4
  import { BrandQuickCreateForm } from "../../admin/components/BrandQuickCreateForm";
5
5
  import { apiClient } from "../../../http";
6
6
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -40,7 +40,7 @@ async function loadPublicBrandOptions(query, page) {
40
40
  }
41
41
  export function BrandInlineSelect({ value, onChange, placeholder = "Search brands…", disabled, allowCreate = true, }) {
42
42
  const loadOptions = allowCreate ? loadAdminBrandOptions : loadPublicBrandOptions;
43
- return (_jsx(InlineCreateSelect, { value: value || null, onChange: (v) => onChange(v ?? ""), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, createLabel: "brand", drawerTitle: "Create Brand", renderCreateForm: allowCreate
43
+ return (_jsx(PaginatedSelect, { value: value || null, onChange: (v) => onChange(v ?? ""), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, createLabel: "brand", drawerTitle: "Create Brand", renderCreateForm: allowCreate
44
44
  ? ({ onCreated, onCancel }) => (_jsx(BrandQuickCreateForm, { onSaved: (id, name) => onCreated({ value: id, label: name }), onCancel: onCancel }))
45
45
  : undefined }));
46
46
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { InlineCreateSelect } from "../../../ui/components/InlineCreateSelect";
3
+ import { PaginatedSelect } from "../../../ui/components/PaginatedSelect";
4
4
  import { CategoryQuickCreateForm } from "../../admin/components/CategoryQuickCreateForm";
5
5
  import { apiClient } from "../../../http";
6
6
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -37,7 +37,7 @@ async function loadPublicCategoryOptions(query, _page) {
37
37
  }
38
38
  export function CategoryInlineSelect({ value, onChange, placeholder = "Search categories…", disabled, allowCreate = false, }) {
39
39
  const loadOptions = allowCreate ? loadAdminCategoryOptions : loadPublicCategoryOptions;
40
- return (_jsx(InlineCreateSelect, { value: value || null, onChange: (v) => onChange(v ?? ""), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, createLabel: "category", drawerTitle: "Create Category", renderCreateForm: allowCreate
40
+ return (_jsx(PaginatedSelect, { value: value || null, onChange: (v) => onChange(v ?? ""), loadOptions: loadOptions, placeholder: placeholder, disabled: disabled, createLabel: "category", drawerTitle: "Create Category", renderCreateForm: allowCreate
41
41
  ? ({ onCreated, onCancel }) => (_jsx(CategoryQuickCreateForm, { onSaved: (id, name) => onCreated({ value: id, label: name }), onCancel: onCancel }))
42
42
  : undefined }));
43
43
  }
@@ -135,5 +135,5 @@ export function SellerAddressesView({ apiBase = SELLER_ENDPOINTS.STORE_ADDRESSES
135
135
  const handleDelete = (addr) => setDeleteTargetAddr(addr);
136
136
  const set = (key, value) => setDraft((p) => ({ ...p, [key]: value }));
137
137
  const handleTextField = (key) => (e) => set(key, e.target.value);
138
- return (_jsxs("div", { className: "min-h-screen", children: [_jsxs("div", { className: "sticky z-10 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-4 py-3 flex items-center justify-between", style: { top: "var(--header-height, 0px)" }, children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Pickup Addresses" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mt-0.5", children: "Manage your store's pickup and return locations" })] }), _jsxs(Button, { size: "sm", onClick: openAdd, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "Add Address" })] })] }), _jsxs("div", { className: "py-6 px-4 sm:px-6 max-w-2xl", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx("div", { className: "flex justify-center py-16", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })) : addresses.length === 0 ? (_jsxs(Div, { className: "rounded-xl border-2 border-dashed border-zinc-200 dark:border-slate-700 py-16 flex flex-col items-center gap-3", children: [_jsx(MapPin, { className: "h-8 w-8 text-zinc-300 dark:text-slate-600" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No pickup addresses yet" }), _jsx(Button, { size: "sm", variant: "outline", onClick: openAdd, children: "Add your first address" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Row, { justify: "end", className: "mb-2", children: [_jsx(Button, { size: "sm", variant: listView === "table" ? "primary" : "ghost", onClick: () => setListView("table"), children: "Table" }), _jsx(Button, { size: "sm", variant: listView === "cards" ? "primary" : "ghost", onClick: () => setListView("cards"), children: "Cards" })] }), listView === "cards" ? (_jsx("div", { className: "grid gap-3", children: addresses.map((addr) => (_jsx("div", { className: deletingId === addr.id ? "opacity-50 pointer-events-none" : "", children: _jsx(AddressCard, { address: addr, onEdit: () => openEdit(addr), onDelete: () => handleDelete(addr) }) }, addr.id))) })) : (_jsx("div", { className: "overflow-x-auto rounded-lg border border-zinc-200 dark:border-slate-700", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-zinc-50 dark:bg-slate-800", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Label" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Name" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "City" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Phone" }), _jsx("th", { className: "text-right px-3 py-2 font-semibold", children: "Actions" })] }) }), _jsx("tbody", { children: addresses.map((addr) => (_jsxs("tr", { className: `border-t border-zinc-100 dark:border-slate-700 ${deletingId === addr.id ? "opacity-50" : ""}`, children: [_jsx("td", { className: "px-3 py-2", children: addr.label }), _jsx("td", { className: "px-3 py-2", children: addr.fullName }), _jsxs("td", { className: "px-3 py-2", children: [addr.city, ", ", addr.state] }), _jsx("td", { className: "px-3 py-2 tabular-nums", children: addr.phone }), _jsx("td", { className: "px-3 py-2 text-right", children: _jsxs(Row, { justify: "end", className: "gap-1", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => openEdit(addr), children: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleDelete(addr), children: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label })] }) })] }, addr.id))) })] }) }))] }))] }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: editingId ? "Edit Address" : "Add Address", footer: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", onClick: closeDrawer, className: "flex-1", children: "Cancel" }), _jsx(Button, { onClick: handleSave, disabled: saving, className: "flex-1", children: saving ? "Saving…" : editingId ? "Save Changes" : "Add Address" })] }), children: _jsxs("div", { className: "space-y-4 py-1", children: [saveError && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-error-surface dark:border-red-900/60 px-3 py-2 text-sm text-error", children: saveError })), _jsx(Field, { label: "Label *", hint: "e.g. Warehouse, Shop, Home", children: _jsx("input", { type: "text", value: draft.label, onChange: handleTextField("label"), placeholder: "Warehouse", maxLength: 60, className: INPUT_CLS }) }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "Full Name *", children: _jsx("input", { type: "text", value: draft.fullName, onChange: handleTextField("fullName"), placeholder: "Ravi Kumar", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "Phone *", children: _jsx("input", { type: "tel", value: draft.phone, onChange: handleTextField("phone"), placeholder: "+91 98765 43210", maxLength: 20, className: INPUT_CLS }) })] }), _jsx(Field, { label: "Address Line 1 *", children: _jsx("input", { type: "text", value: draft.addressLine1, onChange: handleTextField("addressLine1"), placeholder: "Shop 12, Main Market", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Address Line 2", children: _jsx("input", { type: "text", value: draft.addressLine2, onChange: handleTextField("addressLine2"), placeholder: "Building / Floor (optional)", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Landmark", children: _jsx("input", { type: "text", value: draft.landmark, onChange: handleTextField("landmark"), placeholder: "Near metro station (optional)", maxLength: 100, className: INPUT_CLS }) }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "City *", children: _jsx("input", { type: "text", value: draft.city, onChange: handleTextField("city"), placeholder: "Mumbai", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "State *", children: _jsx("input", { type: "text", value: draft.state, onChange: handleTextField("state"), placeholder: "Maharashtra", maxLength: 100, className: INPUT_CLS }) })] }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "Postal Code *", children: _jsx("input", { type: "text", value: draft.postalCode, onChange: handleTextField("postalCode"), placeholder: "400001", maxLength: 10, className: INPUT_CLS }) }), _jsx(Field, { label: "Country *", children: _jsx("input", { type: "text", value: draft.country, onChange: handleTextField("country"), placeholder: "India", maxLength: 60, className: INPUT_CLS }) })] }), _jsxs("label", { className: "flex items-center gap-3 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: draft.isDefault, onChange: (e) => set("isDefault", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsx("span", { className: "text-sm text-zinc-700 dark:text-zinc-300", children: "Set as default pickup address" })] })] }) }), deleteTargetAddr && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Address", message: `Delete address "${deleteTargetAddr.label}"? This cannot be undone.`, onConfirm: () => { deleteById(deleteTargetAddr.id); setDeleteTargetAddr(null); }, onClose: () => setDeleteTargetAddr(null), isDeleting: deletingId === deleteTargetAddr.id }))] }));
138
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsxs("div", { className: "sticky z-10 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-4 py-3 flex items-center justify-between", style: { top: "var(--header-height, 0px)" }, children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Pickup Addresses" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mt-0.5", children: "Manage your store's pickup and return locations" })] }), _jsxs(Button, { size: "sm", onClick: openAdd, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "Add Address" })] })] }), _jsxs("div", { className: "py-6 px-4 sm:px-6 max-w-2xl", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-error/20 bg-error-surface px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx("div", { className: "flex justify-center py-16", children: _jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[var(--appkit-color-primary)] border-t-transparent" }) })) : addresses.length === 0 ? (_jsxs(Div, { className: "rounded-xl border-2 border-dashed border-zinc-200 dark:border-slate-700 py-16 flex flex-col items-center gap-3", children: [_jsx(MapPin, { className: "h-8 w-8 text-zinc-300 dark:text-slate-600" }), _jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No pickup addresses yet" }), _jsx(Button, { size: "sm", variant: "outline", onClick: openAdd, children: "Add your first address" })] })) : (_jsxs(_Fragment, { children: [_jsxs(Row, { justify: "end", className: "mb-2", children: [_jsx(Button, { size: "sm", variant: listView === "table" ? "primary" : "ghost", onClick: () => setListView("table"), children: "Table" }), _jsx(Button, { size: "sm", variant: listView === "cards" ? "primary" : "ghost", onClick: () => setListView("cards"), children: "Cards" })] }), listView === "cards" ? (_jsx("div", { className: "grid gap-3", children: addresses.map((addr) => (_jsx("div", { className: deletingId === addr.id ? "opacity-50 pointer-events-none" : "", children: _jsx(AddressCard, { address: addr, onEdit: () => openEdit(addr), onDelete: () => handleDelete(addr) }) }, addr.id))) })) : (_jsx("div", { className: "overflow-x-auto rounded-lg border border-zinc-200 dark:border-slate-700", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-zinc-50 dark:bg-slate-800", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Label" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Name" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "City" }), _jsx("th", { className: "text-left px-3 py-2 font-semibold", children: "Phone" }), _jsx("th", { className: "text-right px-3 py-2 font-semibold", children: "Actions" })] }) }), _jsx("tbody", { children: addresses.map((addr) => (_jsxs("tr", { className: `border-t border-zinc-100 dark:border-slate-700 ${deletingId === addr.id ? "opacity-50" : ""}`, children: [_jsx("td", { className: "px-3 py-2", children: addr.label }), _jsx("td", { className: "px-3 py-2", children: addr.fullName }), _jsxs("td", { className: "px-3 py-2", children: [addr.city, ", ", addr.state] }), _jsx("td", { className: "px-3 py-2 tabular-nums", children: addr.phone }), _jsx("td", { className: "px-3 py-2 text-right", children: _jsxs(Row, { justify: "end", className: "gap-1", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: () => openEdit(addr), children: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => handleDelete(addr), children: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label })] }) })] }, addr.id))) })] }) }))] }))] }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: editingId ? "Edit Address" : "Add Address", footer: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", onClick: closeDrawer, className: "flex-1", children: "Cancel" }), _jsx(Button, { onClick: handleSave, disabled: saving, className: "flex-1", children: saving ? "Saving…" : editingId ? "Save Changes" : "Add Address" })] }), children: _jsxs("div", { className: "space-y-4 py-1", children: [saveError && (_jsx(Div, { className: "rounded-lg border border-error/20 bg-error-surface px-3 py-2 text-sm text-error", children: saveError })), _jsx(Field, { label: "Label *", hint: "e.g. Warehouse, Shop, Home", children: _jsx("input", { type: "text", value: draft.label, onChange: handleTextField("label"), placeholder: "Warehouse", maxLength: 60, className: INPUT_CLS }) }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "Full Name *", children: _jsx("input", { type: "text", value: draft.fullName, onChange: handleTextField("fullName"), placeholder: "Ravi Kumar", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "Phone *", children: _jsx("input", { type: "tel", value: draft.phone, onChange: handleTextField("phone"), placeholder: "+91 98765 43210", maxLength: 20, className: INPUT_CLS }) })] }), _jsx(Field, { label: "Address Line 1 *", children: _jsx("input", { type: "text", value: draft.addressLine1, onChange: handleTextField("addressLine1"), placeholder: "Shop 12, Main Market", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Address Line 2", children: _jsx("input", { type: "text", value: draft.addressLine2, onChange: handleTextField("addressLine2"), placeholder: "Building / Floor (optional)", maxLength: 200, className: INPUT_CLS }) }), _jsx(Field, { label: "Landmark", children: _jsx("input", { type: "text", value: draft.landmark, onChange: handleTextField("landmark"), placeholder: "Near metro station (optional)", maxLength: 100, className: INPUT_CLS }) }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "City *", children: _jsx("input", { type: "text", value: draft.city, onChange: handleTextField("city"), placeholder: "Mumbai", maxLength: 100, className: INPUT_CLS }) }), _jsx(Field, { label: "State *", children: _jsx("input", { type: "text", value: draft.state, onChange: handleTextField("state"), placeholder: "Maharashtra", maxLength: 100, className: INPUT_CLS }) })] }), _jsxs("div", { className: CLS_GRID_2_COL, children: [_jsx(Field, { label: "Postal Code *", children: _jsx("input", { type: "text", value: draft.postalCode, onChange: handleTextField("postalCode"), placeholder: "400001", maxLength: 10, className: INPUT_CLS }) }), _jsx(Field, { label: "Country *", children: _jsx("input", { type: "text", value: draft.country, onChange: handleTextField("country"), placeholder: "India", maxLength: 60, className: INPUT_CLS }) })] }), _jsxs("label", { className: "flex items-center gap-3 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: draft.isDefault, onChange: (e) => set("isDefault", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsx("span", { className: "text-sm text-zinc-700 dark:text-zinc-300", children: "Set as default pickup address" })] })] }) }), deleteTargetAddr && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Address", message: `Delete address "${deleteTargetAddr.label}"? This cannot be undone.`, onConfirm: () => { deleteById(deleteTargetAddr.id); setDeleteTargetAddr(null); }, onClose: () => setDeleteTargetAddr(null), isDeleting: deletingId === deleteTargetAddr.id }))] }));
139
139
  }
@@ -1,9 +1,9 @@
1
1
  import React from "react";
2
- import type { ListingViewShellProps } from "../../../ui";
3
- export interface SellerAuctionsViewProps extends ListingViewShellProps {
2
+ import type { ListingLayoutProps } from "../../../ui";
3
+ export interface SellerAuctionsViewProps extends ListingLayoutProps {
4
4
  renderHeader?: (onAdd: () => void) => React.ReactNode;
5
5
  onEditClick?: (id: string) => void;
6
6
  onDelete?: (id: string) => Promise<void>;
7
7
  onBulkDelete?: (ids: string[]) => Promise<void>;
8
8
  }
9
- export declare function SellerAuctionsView({ renderHeader, children, onEditClick, onDelete, onBulkDelete, ...props }: SellerAuctionsViewProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function SellerAuctionsView({ children, onEditClick, onDelete, onBulkDelete, ...props }: SellerAuctionsViewProps): import("react/jsx-runtime").JSX.Element;