@mohasinac/appkit 2.7.58 → 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 (364) 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/scams/og.js +1 -1
  33. package/dist/_internal/server/features/seo/og-layout.d.ts +42 -0
  34. package/dist/_internal/server/features/seo/og-layout.js +69 -0
  35. package/dist/_internal/server/features/stores/og.js +8 -41
  36. package/dist/_internal/server/features/sublisting-categories/og.js +11 -42
  37. package/dist/_internal/shared/actions/bulk-helpers.d.ts +3 -0
  38. package/dist/_internal/shared/actions/bulk-helpers.js +19 -0
  39. package/dist/_internal/shared/config/schema.d.ts +4 -4
  40. package/dist/client.d.ts +13 -6
  41. package/dist/client.js +9 -3
  42. package/dist/configs/next.js +11 -0
  43. package/dist/constants/index.d.ts +4 -0
  44. package/dist/constants/index.js +2 -0
  45. package/dist/constants/notification-types.d.ts +20 -0
  46. package/dist/constants/notification-types.js +37 -0
  47. package/dist/constants/pagination-presets.d.ts +39 -0
  48. package/dist/constants/pagination-presets.js +38 -0
  49. package/dist/errors/messages.d.ts +0 -4
  50. package/dist/errors/messages.js +0 -4
  51. package/dist/features/account/components/AddressesIndexListing.js +3 -4
  52. package/dist/features/account/components/UserOffersPanel.js +1 -1
  53. package/dist/features/account/components/UserSidebar.js +14 -10
  54. package/dist/features/account/components/UserSupportView.d.ts +1 -2
  55. package/dist/features/account/components/UserSupportView.js +9 -1
  56. package/dist/features/admin/actions/admin-actions.js +16 -1
  57. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +2 -3
  58. package/dist/features/admin/components/AdminAllEventEntriesView.js +50 -89
  59. package/dist/features/admin/components/AdminBidsView.d.ts +2 -3
  60. package/dist/features/admin/components/AdminBidsView.js +64 -104
  61. package/dist/features/admin/components/AdminBlogView.d.ts +3 -7
  62. package/dist/features/admin/components/AdminBlogView.js +53 -88
  63. package/dist/features/admin/components/AdminBrandEditorView.js +14 -17
  64. package/dist/features/admin/components/AdminBrandsView.d.ts +2 -3
  65. package/dist/features/admin/components/AdminBrandsView.js +85 -89
  66. package/dist/features/admin/components/AdminBundlesView.js +68 -130
  67. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -2
  68. package/dist/features/admin/components/AdminCarouselView.js +22 -70
  69. package/dist/features/admin/components/AdminCartsView.d.ts +2 -3
  70. package/dist/features/admin/components/AdminCartsView.js +39 -89
  71. package/dist/features/admin/components/AdminCategoriesView.d.ts +3 -3
  72. package/dist/features/admin/components/AdminCategoriesView.js +97 -96
  73. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -6
  74. package/dist/features/admin/components/AdminClassifiedView.d.ts +3 -0
  75. package/dist/features/admin/components/AdminClassifiedView.js +44 -0
  76. package/dist/features/admin/components/AdminContactView.d.ts +2 -2
  77. package/dist/features/admin/components/AdminContactView.js +105 -130
  78. package/dist/features/admin/components/AdminCouponEditorView.js +14 -17
  79. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -6
  80. package/dist/features/admin/components/AdminCouponsView.js +69 -97
  81. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +3 -0
  82. package/dist/features/admin/components/AdminDigitalCodesView.js +51 -0
  83. package/dist/features/admin/components/AdminFaqEditorView.js +14 -17
  84. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -4
  85. package/dist/features/admin/components/AdminFaqsView.js +79 -86
  86. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -9
  87. package/dist/features/admin/components/AdminFeaturesView.d.ts +2 -3
  88. package/dist/features/admin/components/AdminFeaturesView.js +57 -70
  89. package/dist/features/admin/components/AdminGroupedListingsView.d.ts +3 -0
  90. package/dist/features/admin/components/AdminGroupedListingsView.js +43 -0
  91. package/dist/features/admin/components/AdminHistoryView.d.ts +2 -3
  92. package/dist/features/admin/components/AdminHistoryView.js +35 -52
  93. package/dist/features/admin/components/AdminListingScaffold.d.ts +2 -2
  94. package/dist/features/admin/components/AdminListingScaffold.js +3 -3
  95. package/dist/features/admin/components/AdminLiveView.d.ts +3 -0
  96. package/dist/features/admin/components/AdminLiveView.js +50 -0
  97. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -2
  98. package/dist/features/admin/components/AdminNewsletterView.js +68 -108
  99. package/dist/features/admin/components/AdminNotificationsView.d.ts +2 -3
  100. package/dist/features/admin/components/AdminNotificationsView.js +67 -99
  101. package/dist/features/admin/components/AdminOrderEditorView.js +10 -10
  102. package/dist/features/admin/components/AdminOrdersView.d.ts +2 -3
  103. package/dist/features/admin/components/AdminOrdersView.js +93 -113
  104. package/dist/features/admin/components/AdminPayoutsView.d.ts +2 -3
  105. package/dist/features/admin/components/AdminPayoutsView.js +51 -97
  106. package/dist/features/admin/components/AdminPrizeDrawsView.d.ts +2 -3
  107. package/dist/features/admin/components/AdminPrizeDrawsView.js +41 -83
  108. package/dist/features/admin/components/AdminProductEditorView.js +3 -7
  109. package/dist/features/admin/components/AdminProductsView.d.ts +4 -4
  110. package/dist/features/admin/components/AdminProductsView.js +166 -167
  111. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +1 -1
  112. package/dist/features/admin/components/AdminReturnRequestsView.js +64 -66
  113. package/dist/features/admin/components/AdminReviewsView.d.ts +3 -7
  114. package/dist/features/admin/components/AdminReviewsView.js +94 -116
  115. package/dist/features/admin/components/AdminScammersView.d.ts +2 -3
  116. package/dist/features/admin/components/AdminScammersView.js +53 -103
  117. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  118. package/dist/features/admin/components/AdminSessionsView.d.ts +2 -3
  119. package/dist/features/admin/components/AdminSessionsView.js +62 -95
  120. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +1 -1
  121. package/dist/features/admin/components/AdminStoreAddressesView.js +39 -53
  122. package/dist/features/admin/components/AdminStoreEditorView.js +21 -8
  123. package/dist/features/admin/components/AdminStoresView.d.ts +2 -3
  124. package/dist/features/admin/components/AdminStoresView.js +67 -105
  125. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +1 -1
  126. package/dist/features/admin/components/AdminSublistingCategoriesView.js +29 -49
  127. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +17 -20
  128. package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +10 -1
  129. package/dist/features/admin/components/AdminSupportTicketDetailView.js +191 -5
  130. package/dist/features/admin/components/AdminSupportTicketsView.d.ts +2 -3
  131. package/dist/features/admin/components/AdminSupportTicketsView.js +65 -102
  132. package/dist/features/admin/components/AdminTeamView.d.ts +2 -2
  133. package/dist/features/admin/components/AdminTeamView.js +42 -85
  134. package/dist/features/admin/components/AdminUserEditorView.d.ts +11 -1
  135. package/dist/features/admin/components/AdminUserEditorView.js +80 -6
  136. package/dist/features/admin/components/AdminUsersView.d.ts +2 -3
  137. package/dist/features/admin/components/AdminUsersView.js +108 -106
  138. package/dist/features/admin/components/AdminViewCards.d.ts +1 -1
  139. package/dist/features/admin/components/AdminWishlistsView.d.ts +2 -3
  140. package/dist/features/admin/components/AdminWishlistsView.js +36 -62
  141. package/dist/features/admin/components/DataListingView.d.ts +122 -0
  142. package/dist/features/admin/components/DataListingView.js +66 -0
  143. package/dist/features/admin/components/index.d.ts +10 -4
  144. package/dist/features/admin/components/index.js +6 -2
  145. package/dist/features/admin/constants/filter-tabs.d.ts +23 -17
  146. package/dist/features/admin/constants/filter-tabs.js +21 -17
  147. package/dist/features/admin/hooks/useAdminListing.d.ts +59 -0
  148. package/dist/features/admin/hooks/useAdminListing.js +71 -0
  149. package/dist/features/admin/schemas/firestore.js +6 -7
  150. package/dist/features/auctions/server.d.ts +0 -1
  151. package/dist/features/auctions/server.js +0 -1
  152. package/dist/features/auth/actions/realtime-token-actions.js +1 -1
  153. package/dist/features/auth/repository/user.repository.js +1 -1
  154. package/dist/features/auth/schemas/firestore.d.ts +1 -0
  155. package/dist/features/blog/components/BlogIndexListing.js +3 -6
  156. package/dist/features/cart/repository/cart.repository.d.ts +4 -1
  157. package/dist/features/cart/repository/cart.repository.js +12 -0
  158. package/dist/features/categories/components/CategoriesIndexListing.js +3 -6
  159. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -2
  160. package/dist/features/checkout/index.d.ts +1 -1
  161. package/dist/features/events/components/AdminEventsView.d.ts +3 -3
  162. package/dist/features/events/components/AdminEventsView.js +50 -86
  163. package/dist/features/events/components/EventOfferCard.d.ts +19 -0
  164. package/dist/features/events/components/EventOfferCard.js +29 -0
  165. package/dist/features/events/components/EventRaffleEntryForm.d.ts +25 -0
  166. package/dist/features/events/components/EventRaffleEntryForm.js +37 -0
  167. package/dist/features/events/components/EventRafflesSection.d.ts +1 -4
  168. package/dist/features/events/components/EventRafflesSection.js +17 -6
  169. package/dist/features/events/components/EventSaleBanner.d.ts +21 -0
  170. package/dist/features/events/components/EventSaleBanner.js +18 -0
  171. package/dist/features/events/components/EventsIndexListing.js +3 -4
  172. package/dist/features/events/components/index.d.ts +6 -0
  173. package/dist/features/events/components/index.js +4 -0
  174. package/dist/features/events/repository/event-entry.repository.d.ts +5 -0
  175. package/dist/features/events/repository/event-entry.repository.js +7 -0
  176. package/dist/features/filters/AsyncFacetSection.d.ts +1 -1
  177. package/dist/features/homepage/components/AnnouncementBar.d.ts +4 -1
  178. package/dist/features/homepage/components/AnnouncementBar.js +51 -4
  179. package/dist/features/homepage/components/FAQSection.d.ts +0 -5
  180. package/dist/features/homepage/components/MarketplaceHomepageView.d.ts +3 -1
  181. package/dist/features/homepage/components/MarketplaceHomepageView.js +2 -2
  182. package/dist/features/homepage/components/index.d.ts +1 -1
  183. package/dist/features/homepage/components/index.js +1 -1
  184. package/dist/features/homepage/lib/live-stats.js +1 -1
  185. package/dist/features/homepage/lib/section-renderer.d.ts +2 -2
  186. package/dist/features/homepage/lib/section-renderer.js +2 -2
  187. package/dist/features/homepage/schemas/firestore.d.ts +0 -2
  188. package/dist/features/layout/index.d.ts +0 -2
  189. package/dist/features/layout/index.js +0 -1
  190. package/dist/features/orders/repository/orders.repository.d.ts +0 -1
  191. package/dist/features/orders/repository/orders.repository.js +0 -1
  192. package/dist/features/orders/server.d.ts +1 -1
  193. package/dist/features/orders/server.js +1 -1
  194. package/dist/features/pre-orders/server.d.ts +0 -1
  195. package/dist/features/pre-orders/server.js +0 -1
  196. package/dist/features/products/components/GroupSettingsPanel.js +65 -49
  197. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  198. package/dist/features/products/components/PrizeDrawsSection.d.ts +1 -4
  199. package/dist/features/products/components/PrizeDrawsSection.js +17 -6
  200. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  201. package/dist/features/products/components/ProductCardMetadataSection.d.ts +11 -0
  202. package/dist/features/products/components/ProductCardMetadataSection.js +25 -0
  203. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  204. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  205. package/dist/features/products/components/ProductGradingTab.d.ts +13 -0
  206. package/dist/features/products/components/ProductGradingTab.js +25 -0
  207. package/dist/features/products/components/ProductGrid.js +14 -2
  208. package/dist/features/products/components/ProductTabsShell.d.ts +5 -1
  209. package/dist/features/products/components/ProductTabsShell.js +6 -1
  210. package/dist/features/products/components/index.d.ts +4 -0
  211. package/dist/features/products/components/index.js +3 -0
  212. package/dist/features/products/constants/action-defs.d.ts +5 -0
  213. package/dist/features/products/constants/action-defs.js +52 -32
  214. package/dist/features/products/constants/sieve.d.ts +24 -4
  215. package/dist/features/products/constants/sieve.js +20 -11
  216. package/dist/features/products/repository/products.repository.d.ts +0 -2
  217. package/dist/features/products/repository/products.repository.js +0 -2
  218. package/dist/features/products/schemas/firestore.d.ts +17 -0
  219. package/dist/features/products/schemas/product-features.validators.d.ts +2 -2
  220. package/dist/features/products/schemas/product-templates.d.ts +2 -4
  221. package/dist/features/products/server.d.ts +1 -1
  222. package/dist/features/products/server.js +1 -1
  223. package/dist/features/products/types/index.d.ts +4 -0
  224. package/dist/features/promotions/components/CouponCard.js +5 -5
  225. package/dist/features/promotions/components/CouponsIndexListing.js +3 -2
  226. package/dist/features/promotions/server.d.ts +0 -1
  227. package/dist/features/promotions/server.js +0 -1
  228. package/dist/features/reviews/components/ReviewsIndexListing.js +3 -4
  229. package/dist/features/reviews/repository/reviews.repository.d.ts +0 -1
  230. package/dist/features/reviews/repository/reviews.repository.js +0 -1
  231. package/dist/features/reviews/server.d.ts +1 -1
  232. package/dist/features/reviews/server.js +1 -1
  233. package/dist/features/search/api/route.js +44 -1
  234. package/dist/features/search/components/Search.js +2 -0
  235. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  236. package/dist/features/search/hooks/useNavSuggestions.js +31 -4
  237. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  238. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  239. package/dist/features/seller/components/SellerAddressesView.js +10 -20
  240. package/dist/features/seller/components/SellerAuctionsView.d.ts +3 -3
  241. package/dist/features/seller/components/SellerAuctionsView.js +67 -106
  242. package/dist/features/seller/components/SellerBidsView.js +6 -6
  243. package/dist/features/seller/components/SellerBundlesView.js +72 -105
  244. package/dist/features/seller/components/SellerClassifiedView.js +74 -105
  245. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  246. package/dist/features/seller/components/SellerCouponsView.d.ts +2 -2
  247. package/dist/features/seller/components/SellerCouponsView.js +51 -96
  248. package/dist/features/seller/components/SellerDigitalCodesView.js +70 -103
  249. package/dist/features/seller/components/SellerGroupedListingsView.js +34 -54
  250. package/dist/features/seller/components/SellerLiveView.js +70 -99
  251. package/dist/features/seller/components/SellerOffersPanel.js +1 -1
  252. package/dist/features/seller/components/SellerOffersView.d.ts +2 -2
  253. package/dist/features/seller/components/SellerOffersView.js +37 -70
  254. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -2
  255. package/dist/features/seller/components/SellerOrdersView.js +10 -24
  256. package/dist/features/seller/components/SellerPayoutMethodsView.js +12 -24
  257. package/dist/features/seller/components/SellerPayoutsView.d.ts +2 -2
  258. package/dist/features/seller/components/SellerPayoutsView.js +34 -69
  259. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -2
  260. package/dist/features/seller/components/SellerPreOrdersView.js +55 -97
  261. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -2
  262. package/dist/features/seller/components/SellerPrizeDrawsView.js +55 -97
  263. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  264. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +1 -1
  265. package/dist/features/seller/components/SellerProductsFilterDrawer.js +3 -6
  266. package/dist/features/seller/components/SellerProductsView.d.ts +2 -2
  267. package/dist/features/seller/components/SellerProductsView.js +24 -32
  268. package/dist/features/seller/components/SellerShippingConfigsView.js +12 -24
  269. package/dist/features/seller/components/SellerSidebar.d.ts +0 -4
  270. package/dist/features/seller/components/SellerSidebar.js +0 -2
  271. package/dist/features/seller/components/SellerStoreCategoriesView.js +15 -34
  272. package/dist/features/seller/components/SellerTemplatesView.js +27 -43
  273. package/dist/features/seller/components/SellersListView.d.ts +1 -2
  274. package/dist/features/seller/components/analytics/SellerAnalyticsStats.d.ts +5 -0
  275. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +2 -8
  276. package/dist/features/seller/components/index.d.ts +0 -3
  277. package/dist/features/seller/components/index.js +0 -2
  278. package/dist/features/seller/server.d.ts +0 -1
  279. package/dist/features/seller/server.js +0 -1
  280. package/dist/features/shell/FormShell.d.ts +1 -1
  281. package/dist/features/shell/FormShell.js +4 -1
  282. package/dist/features/shell/field-groups/ImageFieldGroup.d.ts +18 -0
  283. package/dist/features/shell/field-groups/ImageFieldGroup.js +15 -0
  284. package/dist/features/shell/field-groups/SeoFieldGroup.d.ts +22 -0
  285. package/dist/features/shell/field-groups/SeoFieldGroup.js +16 -0
  286. package/dist/features/shell/field-groups/StatusFieldGroup.d.ts +35 -0
  287. package/dist/features/shell/field-groups/StatusFieldGroup.js +16 -0
  288. package/dist/features/shell/field-groups/TitleDescriptionGroup.d.ts +40 -0
  289. package/dist/features/shell/field-groups/TitleDescriptionGroup.js +16 -0
  290. package/dist/features/shell/field-groups/index.d.ts +13 -0
  291. package/dist/features/shell/field-groups/index.js +9 -0
  292. package/dist/features/shell/index.d.ts +2 -0
  293. package/dist/features/shell/index.js +1 -0
  294. package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +1 -2
  295. package/dist/features/stores/components/StoreFinanceGuideView.d.ts +1 -2
  296. package/dist/features/stores/components/StoreHeader.js +2 -1
  297. package/dist/features/stores/components/StoreListingsGuideView.d.ts +1 -2
  298. package/dist/features/stores/components/StoreOrdersGuideView.d.ts +1 -2
  299. package/dist/features/stores/components/StoreReviewsListing.js +3 -4
  300. package/dist/features/stores/components/StoreScopedSearch.d.ts +16 -0
  301. package/dist/features/stores/components/StoreScopedSearch.js +27 -0
  302. package/dist/features/stores/components/StoreSettingsGuideView.d.ts +1 -2
  303. package/dist/features/stores/components/StoresIndexListing.js +3 -4
  304. package/dist/features/stores/server.d.ts +0 -1
  305. package/dist/features/stores/server.js +0 -1
  306. package/dist/features/support/schemas/firestore.d.ts +22 -1
  307. package/dist/features/support/schemas/firestore.js +10 -0
  308. package/dist/features/wishlist/server.d.ts +0 -1
  309. package/dist/features/wishlist/server.js +0 -1
  310. package/dist/index.d.ts +11 -33
  311. package/dist/index.js +17 -62
  312. package/dist/next/routing/route-map.d.ts +8 -0
  313. package/dist/next/routing/route-map.js +4 -0
  314. package/dist/react/contexts/SessionContext.d.ts +2 -0
  315. package/dist/react/contexts/SessionContext.js +2 -0
  316. package/dist/react/hooks/useEntityDelete.d.ts +15 -0
  317. package/dist/react/hooks/useEntityDelete.js +39 -0
  318. package/dist/react/hooks/useListingTypeFlags.d.ts +32 -0
  319. package/dist/react/hooks/useListingTypeFlags.js +19 -0
  320. package/dist/react/index.d.ts +2 -0
  321. package/dist/react/index.js +2 -0
  322. package/dist/repositories/index.d.ts +3 -3
  323. package/dist/repositories/index.js +3 -3
  324. package/dist/security/index.d.ts +1 -1
  325. package/dist/security/index.js +1 -1
  326. package/dist/security/pii-redact.d.ts +8 -0
  327. package/dist/security/pii-redact.js +10 -1
  328. package/dist/seed/grouped-listings-seed-data.d.ts +4 -0
  329. package/dist/seed/products-preorders-seed-data.d.ts +4 -0
  330. package/dist/seed/products-prize-draws-seed-data.js +3 -0
  331. package/dist/seed/site-settings-seed-data.js +5 -5
  332. package/dist/seed/sub-listings-seed-data.d.ts +4 -0
  333. package/dist/server.d.ts +2 -0
  334. package/dist/server.js +4 -0
  335. package/dist/styles.css +54 -395
  336. package/dist/tailwind-utilities.css +1 -1
  337. package/dist/ui/components/BaseListingCard.d.ts +10 -0
  338. package/dist/ui/components/BaseListingCard.js +17 -1
  339. package/dist/ui/components/DetailPageGallery.d.ts +32 -0
  340. package/dist/ui/components/DetailPageGallery.js +47 -0
  341. package/dist/ui/components/DetailPageHero.d.ts +30 -0
  342. package/dist/ui/components/DetailPageHero.js +22 -0
  343. package/dist/ui/components/DetailPageTabs.d.ts +34 -0
  344. package/dist/ui/components/DetailPageTabs.js +38 -0
  345. package/dist/ui/components/HorizontalScroller.style.css +15 -2
  346. package/dist/ui/components/ListingFilterDrawer.d.ts +10 -0
  347. package/dist/ui/components/ListingFilterDrawer.js +8 -0
  348. package/dist/ui/components/ListingLayout.d.ts +11 -2
  349. package/dist/ui/components/ListingLayout.js +12 -6
  350. package/dist/ui/components/PaginatedSelect.d.ts +66 -0
  351. package/dist/ui/components/PaginatedSelect.js +201 -0
  352. package/dist/ui/components/PaginatedSelect.style.css +254 -0
  353. package/dist/ui/components/Semantic.d.ts +0 -4
  354. package/dist/ui/components/Semantic.js +0 -2
  355. package/dist/ui/components/SettingsSection.d.ts +47 -0
  356. package/dist/ui/components/SettingsSection.js +38 -0
  357. package/dist/ui/components/index.style.css +1 -4
  358. package/dist/ui/index.d.ts +14 -14
  359. package/dist/ui/index.js +7 -7
  360. package/dist/utils/id-generators.d.ts +1 -18
  361. package/dist/utils/id-generators.js +51 -18
  362. package/dist/validation/schemas.d.ts +25 -0
  363. package/dist/validation/schemas.js +28 -0
  364. package/package.json +1 -1
@@ -1,12 +1,13 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React, { useState, useCallback } from "react";
4
+ import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
4
5
  import { useActionDispatch } from "../../../react/hooks/use-action-dispatch";
5
6
  import { Eye, EyeOff, Pencil, Trash2, Printer, MapPin } from "lucide-react";
6
7
  import { PhysicalLocationModal } from "./PhysicalLocationModal";
7
8
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
8
9
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
9
- import { Alert, Badge, BulkActionBar, Button, Div, ListingToolbar, ListingViewShell, Pagination, Row, Span, Text, useToast } from "../../../ui";
10
+ import { Alert, Badge, BulkActionBar, Button, Div, ListingToolbar, ListingLayout, Pagination, Row, Span, Text, useToast } from "../../../ui";
10
11
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
11
12
  import { SELLER_PRODUCT_STATUS_TABS } from "../../admin/constants/filter-tabs";
12
13
  import { ROUTES } from "../../../constants";
@@ -14,6 +15,8 @@ import { normalizeListingType } from "../../products/utils/listing-type";
14
15
  import { toRecordArray, toRelativeDate, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
15
16
  import { DataTable } from "../../admin/components/DataTable";
16
17
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
18
+ import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
19
+ import { useListingTypeFlags } from "../../../react/hooks/useListingTypeFlags";
17
20
  import { SellerProductsCards } from "./SellerProductsCards";
18
21
  import { SellerProductsFilterDrawer } from "./SellerProductsFilterDrawer";
19
22
  import { KIND_BADGE_VARIANT } from "./seller-products-styles";
@@ -42,17 +45,21 @@ const STATUS_OPTIONS = SELLER_PRODUCT_STATUS_TABS;
42
45
  // S-STORE-2-A — `<TypeDropdown>` replaces the legacy chip strip. Same width on
43
46
  // mobile, narrower on desktop. Drives the `?listingType=` query param.
44
47
  function TypeDropdown({ active, onChange, }) {
48
+ const flags = useListingTypeFlags();
49
+ // W1-43 — hide disabled types so the seller can't filter for an
50
+ // inactive listing surface. Bundle is a categoryType (not a listingType)
51
+ // and stays unconditionally available.
45
52
  const options = [
46
53
  { value: "all", label: "All listings" },
47
- { value: "standard", label: "Standard" },
48
- { value: "auction", label: "Auction" },
49
- { value: "pre-order", label: "Pre-order" },
50
- { value: "prize-draw", label: "Prize Draw" },
54
+ flags.standard && { value: "standard", label: "Standard" },
55
+ flags.auction && { value: "auction", label: "Auction" },
56
+ flags["pre-order"] && { value: "pre-order", label: "Pre-order" },
57
+ flags["prize-draw"] && { value: "prize-draw", label: "Prize Draw" },
51
58
  { value: "bundle", label: "Bundle" },
52
- { value: "classified", label: "Classified" },
53
- { value: "digital-code", label: "Digital Code" },
54
- { value: "live", label: "Live" },
55
- ];
59
+ flags.classified && { value: "classified", label: "Classified" },
60
+ flags["digital-code"] && { value: "digital-code", label: "Digital Code" },
61
+ flags.live && { value: "live", label: "Live" },
62
+ ].filter(Boolean);
56
63
  return (_jsxs(Row, { className: "gap-2 px-3 lg:px-4 py-2 border-b border-[var(--appkit-color-border)]", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: "Listing type" }), _jsx("select", { value: active, onChange: (e) => onChange(e.target.value), className: "rounded border border-[var(--appkit-color-border)] bg-transparent px-2 py-1 text-sm sm:max-w-xs", "aria-label": "Filter by listing type", children: options.map((o) => (_jsx("option", { value: o.value, children: o.label }, o.value))) })] }));
57
64
  }
58
65
  const PRODUCT_COLUMNS = [
@@ -111,7 +118,10 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
111
118
  const [filterOpen, setFilterOpen] = useState(false);
112
119
  // listingKind is URL-driven so it survives navigation and back/forward
113
120
  const listingKind = (table.get("listingType") || "all");
114
- const [deletingId, setDeletingId] = useState(null);
121
+ const { deletingId, handleDelete: performDelete } = useEntityDelete({
122
+ deleteFn: onDeleteProduct,
123
+ onSuccess: (id) => { setDeletedIds((prev) => new Set([...prev, id])); },
124
+ });
115
125
  const [deletedIds, setDeletedIds] = useState(new Set());
116
126
  const [publishingId, setPublishingId] = useState(null);
117
127
  const [statusOverrides, setStatusOverrides] = useState(new Map());
@@ -202,7 +212,7 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
202
212
  .map((r) => statusOverrides.has(r.id) ? { ...r, status: statusOverrides.get(r.id) } : r);
203
213
  const selection = useBulkSelection({ items: visibleRows, keyExtractor: (r) => r.id });
204
214
  if (hasChildren) {
205
- return (_jsx(ListingViewShell, { portal: "seller", ...props, children: children }));
215
+ return (_jsx(ListingLayout, { portal: "seller", ...props, children: children }));
206
216
  }
207
217
  const handleEdit = (row) => {
208
218
  const href = row.listingKind === "auction"
@@ -217,15 +227,7 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
217
227
  const handleDelete = async (row) => {
218
228
  if (!onDeleteProduct)
219
229
  return;
220
- setDeletingId(row.id);
221
- try {
222
- await onDeleteProduct(row.id);
223
- // Optimistically remove from list — avoids a full refetch
224
- setDeletedIds((prev) => new Set([...prev, row.id]));
225
- }
226
- finally {
227
- setDeletingId(null);
228
- }
230
+ await performDelete(row.id);
229
231
  };
230
232
  // S-STORE-2-C — Duplicate verb. Server-side endpoint is /api/store/products/[id]/duplicate.
231
233
  const handleDuplicate = async (row) => {
@@ -283,18 +285,8 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
283
285
  }
284
286
  }, [selection.selectedIds, showToast]);
285
287
  const bulkActions = [
286
- {
287
- id: ACTIONS.STORE["print-labels"].id,
288
- label: ACTIONS.STORE["print-labels"].label,
289
- icon: _jsx(Printer, { className: "w-4 h-4" }),
290
- onClick: handleBulkPrintLabels,
291
- },
292
- {
293
- id: ACTIONS.STORE["set-location"].id,
294
- label: ACTIONS.STORE["set-location"].label,
295
- icon: _jsx(MapPin, { className: "w-4 h-4" }),
296
- onClick: () => setSetLocationOpen(true),
297
- },
288
+ buildBulkAction(ACTIONS.STORE["print-labels"], handleBulkPrintLabels, { icon: _jsx(Printer, { className: "w-4 h-4" }) }),
289
+ buildBulkAction(ACTIONS.STORE["set-location"], () => setSetLocationOpen(true), { icon: _jsx(MapPin, { className: "w-4 h-4" }) }),
298
290
  ];
299
291
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
300
292
  return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products by name\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, toggles: [
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback } from "react";
4
+ import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
4
5
  import { Plus } from "lucide-react";
5
6
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
7
  import { Button, ConfirmDeleteModal, DataTable, Div, ListingToolbar, RowActionMenu, Text, useToast, } from "../../../ui";
@@ -44,7 +45,13 @@ export function SellerShippingConfigsView({ onCreateClick, onEditClick, onDelete
44
45
  const table = useUrlTable({ defaults: { sort: DEFAULT_SORT } });
45
46
  const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
46
47
  const [deleteTargetId, setDeleteTargetId] = useState(null);
47
- const [deletingId, setDeletingId] = useState(null);
48
+ const { deletingId, handleDelete: performDelete } = useEntityDelete({
49
+ endpoint: SELLER_ENDPOINTS.SHIPPING_CONFIG_BY_ID,
50
+ deleteFn: onDelete,
51
+ successMessage: "Shipping config deleted.",
52
+ onSuccess: () => { refetch?.(); },
53
+ fetchOptions: { credentials: "include" },
54
+ });
48
55
  const [settingDefaultId, setSettingDefaultId] = useState(null);
49
56
  const { showToast } = useToast();
50
57
  const commitSearch = useCallback(() => {
@@ -73,28 +80,9 @@ export function SellerShippingConfigsView({ onCreateClick, onEditClick, onDelete
73
80
  })),
74
81
  });
75
82
  const handleDelete = useCallback(async (id) => {
76
- setDeletingId(id);
77
- try {
78
- if (onDelete) {
79
- await onDelete(id);
80
- }
81
- else {
82
- await fetch(SELLER_ENDPOINTS.SHIPPING_CONFIG_BY_ID(id), {
83
- method: "DELETE",
84
- credentials: "include",
85
- });
86
- }
87
- refetch?.();
88
- showToast("Shipping config deleted.", "success");
89
- }
90
- catch (err) {
91
- showToast(err instanceof Error ? err.message : "Failed to delete config.", "error");
92
- }
93
- finally {
94
- setDeletingId(null);
95
- setDeleteTargetId(null);
96
- }
97
- }, [onDelete, refetch, showToast]);
83
+ await performDelete(id);
84
+ setDeleteTargetId(null);
85
+ }, [performDelete]);
98
86
  const handleSetDefault = useCallback(async (id) => {
99
87
  setSettingDefaultId(id);
100
88
  try {
@@ -135,7 +123,7 @@ export function SellerShippingConfigsView({ onCreateClick, onEditClick, onDelete
135
123
  window.location.href = String(ROUTES.STORE.SHIPPING_CONFIGS_EDIT(id));
136
124
  }
137
125
  }, [onEditClick]);
138
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search shipping configs...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Config" })] }) }), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 3 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsxs(Div, { className: "py-16 text-center", children: [_jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No shipping configs yet \u2014 define your first shipping rule" }), _jsx("div", { className: "mt-4", children: _jsx(Button, { size: "sm", onClick: handleCreate, children: "Add shipping config" }) })] })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, actions: (row) => (_jsx(RowActionMenu, { actions: [
126
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search shipping configs...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Config" })] }) }), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 3 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsxs(Div, { className: "py-16 text-center", children: [_jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No shipping configs yet \u2014 define your first shipping rule" }), _jsx("div", { className: "mt-4", children: _jsx(Button, { size: "sm", onClick: handleCreate, children: "Add shipping config" }) })] })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, actions: (row) => (_jsx(RowActionMenu, { actions: [
139
127
  {
140
128
  label: ACTIONS.STORE["edit-listing"].label,
141
129
  onClick: () => handleEdit(row.id),
@@ -25,8 +25,4 @@ interface StoreSidebarProps {
25
25
  className?: string;
26
26
  }
27
27
  export declare function StoreSidebar({ items, groups, activeHref, storeName, storeLogoURL, mobileOpen, desktopOpen, variant, onCloseMobile, onToggle, }: StoreSidebarProps): import("react/jsx-runtime").JSX.Element;
28
- /** @deprecated Use StoreSidebar */
29
- export declare const SellerSidebar: typeof StoreSidebar;
30
- /** @deprecated Use StoreNavItem */
31
- export type SellerNavItem = StoreNavItem;
32
28
  export {};
@@ -62,5 +62,3 @@ export function StoreSidebar({ items, groups, activeHref, storeName, storeLogoUR
62
62
  return (_jsxs(_Fragment, { children: [mounted && mobileOpen &&
63
63
  createPortal(_jsx(DrawerPanel, { title: panelTitle, onClose: close, children: navContent }), document.body), _jsx("div", { className: "md:hidden", children: _jsx(BottomSheet, { open: mobileOpen, onClose: close, title: panelTitle, children: groups ? (_jsx(GroupsContent, { groups: groups, activeHref: activeHref, storeName: storeName, storeLogoURL: storeLogoURL, onItemClick: close })) : (_jsx(FlatContent, { items: items, activeHref: activeHref, storeName: storeName, storeLogoURL: storeLogoURL, onItemClick: close })) }) })] }));
64
64
  }
65
- /** @deprecated Use StoreSidebar */
66
- export const SellerSidebar = StoreSidebar;
@@ -1,13 +1,15 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback } from "react";
4
+ import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
4
5
  import { Plus } from "lucide-react";
5
6
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
7
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
7
- import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, ListingToolbar, Pagination, RowActionMenu, Text, useToast, } from "../../../ui";
8
+ import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, ListingToolbar, Pagination, RowActionMenu, Text, } from "../../../ui";
8
9
  import { useBottomActions } from "../../layout";
9
10
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
10
11
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
+ import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
11
13
  import { ROUTES } from "../../../next";
12
14
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
13
15
  import { TABLE_KEYS } from "../../../constants/table-keys";
@@ -42,8 +44,11 @@ export function SellerStoreCategoriesView({ onCreateClick, onEditClick, onDelete
42
44
  const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
43
45
  const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
44
46
  const [deleteTargetId, setDeleteTargetId] = useState(null);
45
- const [deletingId, setDeletingId] = useState(null);
46
- const { showToast } = useToast();
47
+ const { deletingId, handleDelete: performDelete } = useEntityDelete({
48
+ deleteFn: onDelete,
49
+ successMessage: "Category deleted.",
50
+ onSuccess: () => { refetch?.(); },
51
+ });
47
52
  const commitSearch = useCallback(() => { table.set(TABLE_KEYS.QUERY, searchInput.trim()); }, [searchInput, table]);
48
53
  const resetAll = useCallback(() => {
49
54
  table.setMany({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "" });
@@ -73,37 +78,13 @@ export function SellerStoreCategoriesView({ onCreateClick, onEditClick, onDelete
73
78
  const handleDelete = useCallback(async (id) => {
74
79
  if (!onDelete)
75
80
  return;
76
- setDeletingId(id);
77
- try {
78
- await onDelete(id);
79
- refetch?.();
80
- showToast("Category deleted.", "success");
81
- }
82
- catch (err) {
83
- showToast(err instanceof Error ? err.message : "Failed to delete category.", "error");
84
- }
85
- finally {
86
- setDeletingId(null);
87
- setDeleteTargetId(null);
88
- }
89
- }, [onDelete, refetch, showToast]);
81
+ await performDelete(id);
82
+ setDeleteTargetId(null);
83
+ }, [onDelete, performDelete]);
90
84
  const bulkActions = [
91
- ...(onBulkDelete ? [{
92
- id: "bulk-delete",
93
- label: ACTIONS.STORE["delete-listing"].label,
94
- variant: "danger",
95
- onClick: async () => { await onBulkDelete(selection.selectedIds); selection.clearSelection(); refetch?.(); },
96
- }] : []),
97
- ...(onBulkActivate ? [{
98
- id: "bulk-activate",
99
- label: ACTIONS.ADMIN["activate-bundle"].label,
100
- onClick: async () => { await onBulkActivate(selection.selectedIds); selection.clearSelection(); refetch?.(); },
101
- }] : []),
102
- ...(onBulkDeactivate ? [{
103
- id: "bulk-deactivate",
104
- label: ACTIONS.ADMIN["deactivate-bundle"].label,
105
- onClick: async () => { await onBulkDeactivate(selection.selectedIds); selection.clearSelection(); refetch?.(); },
106
- }] : []),
85
+ ...(onBulkDelete ? [buildBulkAction(ACTIONS.STORE["delete-listing"], async () => { await onBulkDelete(selection.selectedIds); selection.clearSelection(); refetch?.(); })] : []),
86
+ ...(onBulkActivate ? [buildBulkAction(ACTIONS.ADMIN["activate-bundle"], async () => { await onBulkActivate(selection.selectedIds); selection.clearSelection(); refetch?.(); })] : []),
87
+ ...(onBulkDeactivate ? [buildBulkAction(ACTIONS.ADMIN["deactivate-bundle"], async () => { await onBulkDeactivate(selection.selectedIds); selection.clearSelection(); refetch?.(); })] : []),
107
88
  ];
108
89
  const handleNavigateNew = () => {
109
90
  if (onCreateClick) {
@@ -113,7 +94,7 @@ export function SellerStoreCategoriesView({ onCreateClick, onEditClick, onDelete
113
94
  window.location.href = String(ROUTES.STORE.STORE_CATEGORIES_NEW);
114
95
  };
115
96
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
116
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search categories by label...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleNavigateNew, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Category" })] }) }), 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: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No categories yet \u2014 add your first storefront category" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
97
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search categories by label...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleNavigateNew, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Category" })] }) }), 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: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : rows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: "No categories yet \u2014 add your first storefront category" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
117
98
  {
118
99
  label: ACTIONS.STORE["edit-listing"].label,
119
100
  onClick: () => onEditClick
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useMemo } from "react";
4
+ import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
4
5
  import { Plus } from "lucide-react";
5
6
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
7
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
@@ -8,6 +9,7 @@ import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, FilterDrawer
8
9
  import { useBottomActions } from "../../layout";
9
10
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
10
11
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
+ import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
11
13
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
12
14
  import { TABLE_KEYS } from "../../../constants/table-keys";
13
15
  const PAGE_SIZE = 25;
@@ -68,7 +70,13 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
68
70
  const [savingError, setSavingError] = useState(null);
69
71
  // Delete state
70
72
  const [deleteTargetId, setDeleteTargetId] = useState(null);
71
- const [deletingId, setDeletingId] = useState(null);
73
+ const { deletingId, handleDelete: performDelete } = useEntityDelete({
74
+ endpoint: SELLER_ENDPOINTS.TEMPLATE_BY_ID,
75
+ deleteFn: onDelete,
76
+ successMessage: "Template deleted.",
77
+ onSuccess: () => { refetch?.(); },
78
+ fetchOptions: { credentials: "include" },
79
+ });
72
80
  const [duplicatingId, setDuplicatingId] = useState(null);
73
81
  const { showToast } = useToast();
74
82
  const commitSearch = useCallback(() => {
@@ -184,28 +192,9 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
184
192
  }
185
193
  }, [draft, drawerMode, editingId, closeDrawer, refetch, showToast]);
186
194
  const handleDelete = useCallback(async (id) => {
187
- setDeletingId(id);
188
- try {
189
- if (onDelete) {
190
- await onDelete(id);
191
- }
192
- else {
193
- await fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
194
- method: "DELETE",
195
- credentials: "include",
196
- });
197
- }
198
- refetch?.();
199
- showToast("Template deleted.", "success");
200
- }
201
- catch (err) {
202
- showToast(err instanceof Error ? err.message : "Failed to delete template.", "error");
203
- }
204
- finally {
205
- setDeletingId(null);
206
- setDeleteTargetId(null);
207
- }
208
- }, [onDelete, refetch, showToast]);
195
+ await performDelete(id);
196
+ setDeleteTargetId(null);
197
+ }, [performDelete]);
209
198
  const handleDuplicate = useCallback(async (row) => {
210
199
  setDuplicatingId(row.id);
211
200
  try {
@@ -237,27 +226,22 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
237
226
  }
238
227
  }, [onDuplicate, refetch, showToast]);
239
228
  const bulkActions = [
240
- {
241
- id: "bulk-delete",
242
- label: ACTIONS.STORE["delete-template"].label,
243
- variant: "danger",
244
- onClick: async () => {
245
- if (onBulkDelete) {
246
- await onBulkDelete(selection.selectedIds);
247
- }
248
- else {
249
- await Promise.all(selection.selectedIds.map((id) => fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
250
- method: "DELETE",
251
- credentials: "include",
252
- })));
253
- }
254
- selection.clearSelection();
255
- refetch?.();
256
- },
257
- },
229
+ buildBulkAction(ACTIONS.STORE["delete-template"], async () => {
230
+ if (onBulkDelete) {
231
+ await onBulkDelete(selection.selectedIds);
232
+ }
233
+ else {
234
+ await Promise.all(selection.selectedIds.map((id) => fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
235
+ method: "DELETE",
236
+ credentials: "include",
237
+ })));
238
+ }
239
+ selection.clearSelection();
240
+ refetch?.();
241
+ }),
258
242
  ];
259
243
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
260
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), 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: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
244
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), 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: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", 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: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
261
245
  ? "No templates match your search or filters"
262
246
  : "No templates yet — add your first product template" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: pageRows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
263
247
  {
@@ -275,5 +259,5 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
275
259
  onClick: () => setDeleteTargetId(row.id),
276
260
  disabled: deletingId === row.id,
277
261
  },
278
- ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_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: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
262
+ ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_jsx(Div, { className: "rounded-lg border border-error/20 bg-error-surface px-3 py-2 text-sm text-error", children: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
279
263
  }
@@ -1,4 +1,3 @@
1
1
  import type { SlottedListingViewProps } from "../../../ui";
2
- export interface SellersListViewProps extends SlottedListingViewProps {
3
- }
2
+ export type SellersListViewProps = SlottedListingViewProps;
4
3
  export declare function SellersListView(props: SellersListViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,9 @@
1
1
  import type { SellerAnalyticsSummary } from "../../types";
2
+ /**
3
+ * W1-32 — SellerAnalyticsStats now composes AdminStatCard (the only live
4
+ * stat-card primitive after W1-30) instead of redefining its own inline
5
+ * StatCard. Same gradient presets, same visual identity.
6
+ */
2
7
  export interface SellerAnalyticsStatsLabels {
3
8
  totalRevenue?: string;
4
9
  totalOrders?: string;
@@ -2,13 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { TrendingUp, ShoppingBag, Package, CheckCircle } from "lucide-react";
4
4
  import { Div } from "../../../../ui";
5
- const GREEN_GRAD = "linear-gradient(135deg,var(--appkit-color-cobalt,#3570fc) 0%,var(--appkit-color-secondary-400,#84e122) 100%)";
6
- const BRAND_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)";
7
- const AMBER_GRAD = "linear-gradient(135deg,var(--appkit-color-amber-500,#f59e0b) 0%,var(--appkit-color-amber-600,#d97706) 100%)";
8
- const BLUE_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 100%)";
9
- function StatCard({ label, value, gradient, Icon }) {
10
- return (_jsxs(Div, { className: "relative rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden shadow-sm hover:shadow-md transition-shadow", children: [_jsx("div", { className: "absolute top-0 left-0 right-0 h-[3px]", style: { background: gradient }, "aria-hidden": "true" }), _jsxs(Div, { className: "px-5 pb-5 pt-6 flex items-start justify-between gap-3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-widest text-[var(--appkit-color-text-muted)]", children: label }), _jsx("div", { className: "mt-2 text-2xl font-bold text-[var(--appkit-color-text)] tabular-nums leading-none", children: value })] }), _jsx("div", { className: "flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center", style: { background: gradient }, children: _jsx(Icon, { className: "w-5 h-5 text-white" }) })] })] }));
11
- }
5
+ import { AdminStatCard } from "../../../admin/components/analytics/AdminStatCard";
12
6
  export function SellerAnalyticsStats({ summary, labels = {}, formatRevenue = (amount) => String(amount), className = "", }) {
13
- return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(StatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: GREEN_GRAD, Icon: TrendingUp }), _jsx(StatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: BRAND_GRAD, Icon: ShoppingBag }), _jsx(StatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: AMBER_GRAD, Icon: Package }), _jsx(StatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: BLUE_GRAD, Icon: CheckCircle })] }));
7
+ return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(AdminStatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: "green", icon: _jsx(TrendingUp, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: "brand", icon: _jsx(ShoppingBag, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: "amber", icon: _jsx(Package, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: "blue", icon: _jsx(CheckCircle, { className: "w-5 h-5 text-white" }) })] }));
14
8
  }
@@ -1,6 +1,3 @@
1
- export { SellerStatCard } from "./SellerStatCard";
2
- export { SellerSidebar } from "./SellerSidebar";
3
- export type { SellerNavItem } from "./SellerSidebar";
4
1
  export { SellerDashboardView } from "./SellerDashboardView";
5
2
  export type { SellerDashboardViewProps } from "./SellerDashboardView";
6
3
  export { SellerProductsView } from "./SellerProductsView";
@@ -1,5 +1,3 @@
1
- export { SellerStatCard } from "./SellerStatCard";
2
- export { SellerSidebar } from "./SellerSidebar";
3
1
  export { SellerDashboardView } from "./SellerDashboardView";
4
2
  export { SellerProductsView } from "./SellerProductsView";
5
3
  export { SellerAuctionsView } from "./SellerAuctionsView";
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point for seller repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { SellerRepository, PayoutsRepository, } from "./repository/seller.repository";
8
7
  export { OfferRepository, offerRepository, } from "./repository/offer.repository";
9
8
  export { GET as sellerProductsGET } from "./api/products/route";
10
9
  export { GET as sellerStoreGET } from "./api/store/route";
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point for seller repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { SellerRepository, PayoutsRepository, } from "./repository/seller.repository";
8
7
  export { OfferRepository, offerRepository, } from "./repository/offer.repository";
9
8
  export { GET as sellerProductsGET } from "./api/products/route";
10
9
  export { GET as sellerStoreGET } from "./api/store/route";
@@ -40,4 +40,4 @@ export interface UseFormShellResult {
40
40
  markClean: () => void;
41
41
  }
42
42
  export declare function useFormShell(): UseFormShellResult;
43
- export declare function FormShell({ isOpen, onClose, title, breadcrumb, isDirty, isLoading, sections, onSaveDraft, onPublish, saveLabel, publishLabel, renderBottomBar, previewSlot, splitPreview, children, }: FormShellProps): import("react/jsx-runtime").JSX.Element | null;
43
+ export declare function FormShell({ isOpen, onClose, title, breadcrumb, isDirty, isLoading, sections, onSaveDraft, onPublish, saveLabel, publishLabel, renderBottomBar, previewSlot, splitPreview: splitPreviewProp, children, }: FormShellProps): import("react/jsx-runtime").JSX.Element | null;
@@ -15,7 +15,10 @@ export function useFormShell() {
15
15
  };
16
16
  }
17
17
  const FOCUSABLE = 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
18
- export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false, isLoading = false, sections, onSaveDraft, onPublish, saveLabel = FORM_ACTION_META[FORM_ACTION_ID.SAVE_DRAFT].label, publishLabel = FORM_ACTION_META[FORM_ACTION_ID.PUBLISH].label, renderBottomBar, previewSlot, splitPreview = false, children, }) {
18
+ export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false, isLoading = false, sections, onSaveDraft, onPublish, saveLabel = FORM_ACTION_META[FORM_ACTION_ID.SAVE_DRAFT].label, publishLabel = FORM_ACTION_META[FORM_ACTION_ID.PUBLISH].label, renderBottomBar, previewSlot, splitPreview: splitPreviewProp, children, }) {
19
+ // W1-37: auto-enable splitPreview when a previewSlot is provided. Callers
20
+ // can still pass splitPreview={false} explicitly to opt out.
21
+ const splitPreview = splitPreviewProp ?? Boolean(previewSlot);
19
22
  const panelRef = useRef(null);
20
23
  const bodyRef = useRef(null);
21
24
  const [showUnsaved, setShowUnsaved] = useState(false);
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from "react";
2
+ export interface ImageFieldGroupProps {
3
+ /** Slot for the hero / cover image input — wire your own ImageUpload here. */
4
+ heroSlot?: ReactNode;
5
+ /** Slot for an additional gallery input (e.g. MediaUploadField with multi-image). */
6
+ gallerySlot?: ReactNode;
7
+ /** Optional section label override. */
8
+ sectionTitle?: ReactNode;
9
+ sectionDescription?: ReactNode;
10
+ }
11
+ /**
12
+ * `ImageFieldGroup` — wraps hero + gallery image slots in a `SettingsSection`.
13
+ * The actual `<ImageUpload>` / `<MediaUploadField>` instances stay with the
14
+ * consumer because their `onUpload` / context wiring is form-specific.
15
+ *
16
+ * W1-15 — extracted 2026-05-23.
17
+ */
18
+ export declare function ImageFieldGroup({ heroSlot, gallerySlot, sectionTitle, sectionDescription, }: ImageFieldGroupProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { SettingsSection } from "../../../ui/components/SettingsSection";
4
+ /**
5
+ * `ImageFieldGroup` — wraps hero + gallery image slots in a `SettingsSection`.
6
+ * The actual `<ImageUpload>` / `<MediaUploadField>` instances stay with the
7
+ * consumer because their `onUpload` / context wiring is form-specific.
8
+ *
9
+ * W1-15 — extracted 2026-05-23.
10
+ */
11
+ export function ImageFieldGroup({ heroSlot, gallerySlot, sectionTitle = "Images", sectionDescription, }) {
12
+ if (!heroSlot && !gallerySlot)
13
+ return null;
14
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [heroSlot, gallerySlot] }));
15
+ }
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from "react";
2
+ export interface SeoFieldGroupProps {
3
+ seoTitle: string;
4
+ seoDescription: string;
5
+ slug: string;
6
+ onSeoTitleChange: (next: string) => void;
7
+ onSeoDescriptionChange: (next: string) => void;
8
+ onSlugChange?: (next: string) => void;
9
+ /** Read-only computed canonical URL preview (e.g. `https://letitrip.in/products/<slug>`). */
10
+ canonicalPreview?: string;
11
+ /** Optional section label override. */
12
+ sectionTitle?: ReactNode;
13
+ sectionDescription?: ReactNode;
14
+ disabled?: boolean;
15
+ }
16
+ /**
17
+ * `SeoFieldGroup` — shared SEO inputs (title / description / slug) used across
18
+ * Product, Blog, Category, FAQ editors.
19
+ *
20
+ * W1-15 — extracted 2026-05-23.
21
+ */
22
+ export declare function SeoFieldGroup({ seoTitle, seoDescription, slug, onSeoTitleChange, onSeoDescriptionChange, onSlugChange, canonicalPreview, sectionTitle, sectionDescription, disabled, }: SeoFieldGroupProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Input } from "../../../ui/components/Input";
4
+ import { Textarea } from "../../../ui/components/Textarea";
5
+ import { SettingsSection } from "../../../ui/components/SettingsSection";
6
+ const SEO_TITLE_MAX = 60;
7
+ const SEO_DESC_MAX = 160;
8
+ /**
9
+ * `SeoFieldGroup` — shared SEO inputs (title / description / slug) used across
10
+ * Product, Blog, Category, FAQ editors.
11
+ *
12
+ * W1-15 — extracted 2026-05-23.
13
+ */
14
+ export function SeoFieldGroup({ seoTitle, seoDescription, slug, onSeoTitleChange, onSeoDescriptionChange, onSlugChange, canonicalPreview, sectionTitle = "SEO", sectionDescription = "Override the auto-generated metadata if needed. Leave blank to use defaults.", disabled = false, }) {
15
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [_jsx(Input, { label: "SEO title", value: seoTitle, onChange: (e) => onSeoTitleChange(e.target.value), placeholder: "Falls back to the page title", maxLength: SEO_TITLE_MAX, helperText: `Max ${SEO_TITLE_MAX} characters.`, disabled: disabled }), _jsx(Textarea, { label: "SEO description", value: seoDescription, onChange: (e) => onSeoDescriptionChange(e.target.value), placeholder: "Falls back to the page description", maxLength: SEO_DESC_MAX, helperText: `Max ${SEO_DESC_MAX} characters.`, rows: 3, disabled: disabled }), onSlugChange ? (_jsx(Input, { label: "URL slug", value: slug, onChange: (e) => onSlugChange(e.target.value), disabled: disabled, helperText: canonicalPreview ? `Canonical: ${canonicalPreview}` : undefined })) : null] }));
16
+ }