@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
@@ -1,25 +1,14 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import React, { useState, useCallback } from "react";
3
+ import React, { useState } from "react";
4
4
  import { useMutation, useQueryClient } from "@tanstack/react-query";
5
- import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
- import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
7
- import { BulkActionBar, ConfirmDeleteModal, ListingToolbar, ListingViewShell, Pagination, RowActionMenu, Text, useToast, ListingFilterDrawer } from "../../../ui";
5
+ import { ConfirmDeleteModal, ListingLayout, RowActionMenu, Text, useToast } from "../../../ui";
8
6
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
7
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
10
8
  import { ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
11
- import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
12
- import { DataTable } from "./DataTable";
9
+ import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
10
+ import { DataListingView } from "./DataListingView";
13
11
  import { apiClient } from "../../../http";
14
- import { useBottomActions } from "../../layout";
15
- const PAGE_SIZE = 25;
16
- const FILTER_KEYS = ["isActive"];
17
- const DEFAULT_SORT = "-lastActivity";
18
- const SORT_OPTIONS = [
19
- { value: "-lastActivity", label: "Most recent" },
20
- { value: "lastActivity", label: "Least recent" },
21
- { value: "-createdAt", label: "Newest" },
22
- ];
23
12
  function maskIp(ip) {
24
13
  if (!ip)
25
14
  return "—";
@@ -29,51 +18,39 @@ function maskIp(ip) {
29
18
  return ip.replace(/:\w+$/, ":*");
30
19
  }
31
20
  export function AdminSessionsView({ children, ...props }) {
32
- const hasChildren = React.Children.count(children) > 0;
33
- const [view, setView] = useState("table");
34
21
  const queryClient = useQueryClient();
35
22
  const { showToast } = useToast();
36
23
  const [revokeTarget, setRevokeTarget] = useState(null);
37
- const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
38
- const [searchInput, setSearchInput] = useState(table.get("q") || "");
39
- const [filterOpen, setFilterOpen] = useState(false);
40
- const [pendingFilters, setPendingFilters] = useState(() => Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
41
- const openFilters = useCallback(() => {
42
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
43
- setFilterOpen(true);
44
- }, [table]);
45
- const applyFilters = useCallback(() => {
46
- const updates = { page: "1" };
47
- for (const k of FILTER_KEYS)
48
- updates[k] = pendingFilters[k] ?? "";
49
- table.setMany(updates);
50
- setFilterOpen(false);
51
- }, [pendingFilters, table]);
52
- const clearFilters = useCallback(() => {
53
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, ""])));
54
- }, []);
55
- const resetAll = useCallback(() => {
56
- const updates = { q: "", sort: "" };
57
- for (const k of FILTER_KEYS)
58
- updates[k] = "";
59
- table.setMany(updates);
60
- setSearchInput("");
61
- }, [table]);
62
- const commitSearch = useCallback(() => {
63
- table.set("q", searchInput.trim());
64
- }, [searchInput, table]);
65
- const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
66
- const hasActiveState = !!table.get("q") || table.get("sort") !== DEFAULT_SORT || activeFilterCount > 0;
67
- const isActiveRaw = table.get("isActive");
68
- const filters = isActiveRaw ? `isActive==${isActiveRaw}` : undefined;
69
- const { rows, total, isLoading, errorMessage } = useAdminListingData({
24
+ const revokeMutation = useMutation({
25
+ mutationFn: async (id) => {
26
+ await apiClient.delete(ADMIN_ENDPOINTS.SESSION_BY_ID(id));
27
+ },
28
+ onSuccess: () => {
29
+ showToast("Session revoked.", "success");
30
+ queryClient.invalidateQueries({ queryKey: ["admin", "sessions"] });
31
+ setRevokeTarget(null);
32
+ },
33
+ onError: (err) => {
34
+ showToast(err?.message ?? "Failed to revoke session.", "error");
35
+ },
36
+ });
37
+ if (React.Children.count(children) > 0) {
38
+ return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
39
+ }
40
+ const config = {
41
+ portal: "admin",
42
+ title: "Sessions",
43
+ searchPlaceholder: "Search by user or device",
44
+ emptyLabel: "No sessions found",
45
+ filterKeys: ["isActive"],
46
+ defaultSort: "-lastActivity",
70
47
  queryKey: ["admin", "sessions", "listing"],
71
48
  endpoint: ADMIN_ENDPOINTS.SESSIONS,
72
- page: table.getNumber("page", 1),
73
- pageSize: PAGE_SIZE,
74
- sorts: table.get("sort") || DEFAULT_SORT,
75
- filters,
76
- q: table.get("q") || undefined,
49
+ sortOptions: [
50
+ { value: "-lastActivity", label: "Most recent" },
51
+ { value: "lastActivity", label: "Least recent" },
52
+ { value: "-createdAt", label: "Newest" },
53
+ ],
77
54
  mapRows: (response) => toRecordArray(response.sessions).map((item, index) => {
78
55
  const deviceInfo = (item.deviceInfo ?? {});
79
56
  const userLabel = toStringValue(item.user &&
@@ -87,43 +64,39 @@ export function AdminSessionsView({ children, ...props }) {
87
64
  toStringValue(deviceInfo.os, ""),
88
65
  toStringValue(deviceInfo.device, ""),
89
66
  ipMasked,
90
- ].filter(Boolean).join(" · "),
67
+ ]
68
+ .filter(Boolean)
69
+ .join(" · "),
91
70
  status: Boolean(item.isActive) ? "Active" : "Expired",
92
71
  updatedAt: toRelativeDate(item.lastActivity ?? item.createdAt),
93
72
  };
94
73
  }),
95
74
  getTotal: (response, mappedRows) => typeof response.count === "number" ? response.count : mappedRows.length,
96
- });
97
- const revokeMutation = useMutation({
98
- mutationFn: async (id) => {
99
- await apiClient.delete(ADMIN_ENDPOINTS.SESSION_BY_ID(id));
100
- },
101
- onSuccess: () => {
102
- showToast("Session revoked.", "success");
103
- queryClient.invalidateQueries({ queryKey: ["admin", "sessions"] });
104
- setRevokeTarget(null);
105
- },
106
- onError: (err) => {
107
- showToast(err?.message ?? "Failed to revoke session.", "error");
108
- },
109
- });
110
- const currentPage = table.getNumber("page", 1);
111
- const totalPages = Math.ceil(total / PAGE_SIZE);
112
- const selection = useBulkSelection({ items: rows, keyExtractor: (r) => r.id });
113
- if (hasChildren) {
114
- return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
115
- }
116
- useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
117
- { id: ROW_ACTION_ID.REVOKE, label: ACTIONS.ADMIN["revoke-session"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
118
- ] } } : {});
119
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by user or device", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
120
- { id: ROW_ACTION_ID.REVOKE, label: ACTIONS.ADMIN["revoke-session"].label, variant: "secondary", onClick: () => { selection.clearSelection(); } },
121
- ] }), 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) }) })), _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 px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), _jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No sessions found", renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
122
- {
123
- label: ROW_ACTION_META[ROW_ACTION_ID.REVOKE].label,
124
- destructive: ROW_ACTION_META[ROW_ACTION_ID.REVOKE].destructive,
125
- onClick: () => setRevokeTarget(row),
126
- },
127
- ] })) })] }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsxs("div", { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Status" }), _jsx("div", { className: "flex flex-wrap gap-2", children: [{ label: "All", value: "" }, { label: "Active only", value: "true" }].map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, isActive: opt.value })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.isActive || "") === opt.value ? "bg-primary text-white border-primary" : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt.label }, opt.label))) })] }) })] }), _jsx(ConfirmDeleteModal, { isOpen: Boolean(revokeTarget), onClose: () => setRevokeTarget(null), onConfirm: () => { if (revokeTarget)
128
- revokeMutation.mutate(revokeTarget.id); }, isDeleting: revokeMutation.isPending, confirmText: "Revoke", title: "Revoke session?", message: "This will sign the user out of this device immediately.", variant: "danger" })] }));
75
+ buildFilters: (state) => (state.isActive ? `isActive==${state.isActive}` : undefined),
76
+ buildBulkActions: (selection) => [
77
+ {
78
+ id: ROW_ACTION_ID.REVOKE,
79
+ label: ACTIONS.ADMIN["revoke-session"].label,
80
+ variant: "secondary",
81
+ onClick: () => selection.clearSelection(),
82
+ },
83
+ ],
84
+ renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
85
+ {
86
+ label: ROW_ACTION_META[ROW_ACTION_ID.REVOKE].label,
87
+ destructive: ROW_ACTION_META[ROW_ACTION_ID.REVOKE].destructive,
88
+ onClick: () => setRevokeTarget(row),
89
+ },
90
+ ] })),
91
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsxs("div", { className: "space-y-2", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: "Status" }), _jsx("div", { className: "flex flex-wrap gap-2", children: [
92
+ { label: "All", value: "" },
93
+ { label: "Active only", value: "true" },
94
+ ].map((opt) => (_jsx("button", { type: "button", onClick: () => setPendingFilters((p) => ({ ...p, isActive: opt.value })), className: `rounded-full px-3 py-1 text-xs font-medium border transition-colors ${(pendingFilters.isActive || "") === opt.value
95
+ ? "bg-primary text-white border-primary"
96
+ : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: opt.label }, opt.label))) })] })),
97
+ };
98
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(ConfirmDeleteModal, { isOpen: Boolean(revokeTarget), onClose: () => setRevokeTarget(null), onConfirm: () => {
99
+ if (revokeTarget)
100
+ revokeMutation.mutate(revokeTarget.id);
101
+ }, isDeleting: revokeMutation.isPending, confirmText: "Revoke", title: "Revoke session?", message: "This will sign the user out of this device immediately.", variant: "danger" })] }));
129
102
  }
@@ -2,4 +2,4 @@ import React from "react";
2
2
  export interface AdminStoreAddressesViewProps {
3
3
  children?: React.ReactNode;
4
4
  }
5
- export declare function AdminStoreAddressesView({ children: _children }: AdminStoreAddressesViewProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function AdminStoreAddressesView(_props: AdminStoreAddressesViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,56 +1,42 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useCallback } from "react";
4
- import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
- import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
6
- import { ListingToolbar, Pagination } from "../../../ui";
7
- import { toRecordArray, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
8
- import { DataTable } from "./DataTable";
9
- import { AdminViewCards } from "./AdminViewCards";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { toRecordArray, toStringValue, } from "../hooks/useAdminListingData";
4
+ import { DataListingView } from "./DataListingView";
10
5
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
- const PAGE_SIZE = 25;
12
- const DEFAULT_SORT = "storeId";
13
- const SORT_OPTIONS = [
14
- { value: "storeId", label: "Store ID" },
15
- { value: "city", label: "City A–Z" },
16
- ];
17
- export function AdminStoreAddressesView({ children: _children }) {
18
- const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
19
- const [searchInput, setSearchInput] = useState(table.get("q") || "");
20
- const [view, setView] = useState("table");
21
- const resetAll = useCallback(() => {
22
- table.setMany({ q: "", sort: "" });
23
- setSearchInput("");
24
- }, [table]);
25
- const commitSearch = useCallback(() => {
26
- table.set("q", searchInput.trim());
27
- }, [searchInput, table]);
28
- const hasActiveState = !!table.get("q") || table.get("sort") !== DEFAULT_SORT;
29
- const { rows, total, isLoading, errorMessage } = useAdminListingData({
30
- queryKey: ["admin", "store-addresses", "listing"],
31
- endpoint: ADMIN_ENDPOINTS.STORE_ADDRESSES,
32
- page: table.getNumber("page", 1),
33
- pageSize: PAGE_SIZE,
34
- sorts: table.get("sort") || DEFAULT_SORT,
35
- q: table.get("q") || undefined,
36
- mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
37
- id: toStringValue(item.id, `addr-${index}`),
38
- primary: [
39
- toStringValue(item.label, "Address"),
40
- toStringValue(item.city, ""),
41
- toStringValue(item.state, ""),
42
- ].filter(Boolean).join(", "),
43
- secondary: [
44
- toStringValue(item.storeId ?? item.storeName, "Unknown store"),
45
- toStringValue(item.pincode, ""),
46
- ].filter(Boolean).join(" · "),
47
- status: item.isPickupLocation ? "pickup" : "standard",
48
- updatedAt: toStringValue(item.storeId, ""),
49
- })),
50
- getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
51
- });
52
- const currentPage = table.getNumber("page", 1);
53
- const totalPages = Math.ceil(total / PAGE_SIZE);
54
- const selection = useBulkSelection({ items: rows ?? [], keyExtractor: (r) => r.id });
55
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search by label, city, or store ID", 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 }), 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) }) })), _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 px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No store addresses found" })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No store addresses found", onRowClick: undefined, selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] })] }));
6
+ const ADMIN_STORE_ADDRESSES_CONFIG = {
7
+ portal: "admin",
8
+ title: "Store Addresses",
9
+ searchPlaceholder: "Search by label, city, or store ID",
10
+ emptyLabel: "No store addresses found",
11
+ filterKeys: [],
12
+ defaultSort: "storeId",
13
+ queryKey: ["admin", "store-addresses", "listing"],
14
+ endpoint: ADMIN_ENDPOINTS.STORE_ADDRESSES,
15
+ sortOptions: [
16
+ { value: "storeId", label: "Store ID" },
17
+ { value: "city", label: "City A–Z" },
18
+ ],
19
+ mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
20
+ id: toStringValue(item.id, `addr-${index}`),
21
+ primary: [
22
+ toStringValue(item.label, "Address"),
23
+ toStringValue(item.city, ""),
24
+ toStringValue(item.state, ""),
25
+ ]
26
+ .filter(Boolean)
27
+ .join(", "),
28
+ secondary: [
29
+ toStringValue(item.storeId ?? item.storeName, "Unknown store"),
30
+ toStringValue(item.pincode, ""),
31
+ ]
32
+ .filter(Boolean)
33
+ .join(" · "),
34
+ status: item.isPickupLocation ? "pickup" : "standard",
35
+ updatedAt: toStringValue(item.storeId, ""),
36
+ })),
37
+ getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
38
+ buildFilters: () => undefined,
39
+ };
40
+ export function AdminStoreAddressesView(_props) {
41
+ return _jsx(DataListingView, { config: ADMIN_STORE_ADDRESSES_CONFIG });
56
42
  }
@@ -1,11 +1,10 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { useMutation, useQueryClient } from "@tanstack/react-query";
5
- import { Button, Form, FormActions, Select, SideDrawer, Toggle, useToast, } from "../../../ui";
5
+ import { Button, Form, FormActions, Label, Select, SideDrawer, StackedViewShell, Toggle, useToast, } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
- // --- Capability groups -------------------------------------------------------
9
8
  const CAPABILITY_GROUPS = [
10
9
  {
11
10
  label: "Listings",
@@ -47,6 +46,7 @@ const STATUS_OPTIONS = [
47
46
  { label: "Suspended", value: "suspended" },
48
47
  { label: "Rejected", value: "rejected" },
49
48
  ];
49
+ const TEXTAREA_CHROME = "w-full rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500";
50
50
  // --- Component ---------------------------------------------------------------
51
51
  export function AdminStoreEditorView({ open, onClose, storeId, storeName, currentStatus, currentIsVerified, currentCapabilities, }) {
52
52
  const queryClient = useQueryClient();
@@ -97,11 +97,24 @@ export function AdminStoreEditorView({ open, onClose, storeId, storeName, curren
97
97
  showToast(err?.message ?? "Failed to update store.", "error");
98
98
  },
99
99
  });
100
- return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: storeName ? `Manage: ${storeName}` : "Manage Store", children: _jsxs(Form, { onSubmit: (e) => {
100
+ const renderStatusSection = () => (_jsx(Select, { label: "Store status", options: STATUS_OPTIONS, value: storeStatus, onValueChange: setStoreStatus }));
101
+ const renderNotesSection = () => (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { children: "Admin notes (optional)" }), _jsx("textarea", { value: adminNotes, onChange: (e) => setAdminNotes(e.target.value), rows: 3, placeholder: "e.g. Reason for suspension, approval notes\u2026", className: TEXTAREA_CHROME })] }));
102
+ const renderTogglesSection = () => (_jsxs(_Fragment, { children: [_jsx(Toggle, { label: "Verified store", checked: isVerified, onChange: setIsVerified }), _jsx(Toggle, { label: "Featured store", checked: isFeatured, onChange: setIsFeatured })] }));
103
+ const renderSuspensionSection = () => storeStatus === "suspended" ? (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Label, { children: "Suspension reason (optional)" }), _jsx("textarea", { value: suspensionReason, onChange: (e) => setSuspensionReason(e.target.value), rows: 2, placeholder: "e.g. Policy violation, fraudulent activity\u2026", className: TEXTAREA_CHROME })] })) : null;
104
+ const renderCapabilitiesSection = () => (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("span", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: ["Capabilities", _jsxs("span", { className: "ml-2 text-xs font-normal text-zinc-500 dark:text-zinc-400", children: ["(", capabilities.size, " active)"] })] }), _jsx("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 divide-y divide-zinc-100 dark:divide-slate-700", children: CAPABILITY_GROUPS.map((group) => {
105
+ const checked = group.caps.filter((c) => capabilities.has(c.key)).length;
106
+ return (_jsxs("details", { className: "group", children: [_jsxs("summary", { className: "flex cursor-pointer items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wide text-zinc-600 dark:text-zinc-400 select-none hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx("span", { children: group.label }), _jsxs("span", { className: "text-xs font-normal normal-case text-zinc-400 dark:text-zinc-400", children: [checked, "/", group.caps.length] })] }), _jsx("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1.5 px-3 py-2.5 bg-zinc-50/60 dark:bg-slate-800/40", children: group.caps.map((cap) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-xs text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "checkbox", checked: capabilities.has(cap.key), onChange: () => toggleCapability(cap.key), className: "h-3.5 w-3.5 rounded border-zinc-300 dark:border-slate-600 accent-primary" }), cap.label] }, cap.key))) })] }, group.label));
107
+ }) })] }));
108
+ const renderActionsSection = () => (_jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !storeId || saveMutation.isPending, children: "Save changes" })] }));
109
+ return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: storeName ? `Manage: ${storeName}` : "Manage Store", children: _jsx(Form, { onSubmit: (e) => {
101
110
  e.preventDefault();
102
111
  saveMutation.mutate();
103
- }, className: "space-y-4 p-4", children: [_jsx(Select, { label: "Store status", options: STATUS_OPTIONS, value: storeStatus, onValueChange: setStoreStatus }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("label", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Admin notes (optional)" }), _jsx("textarea", { value: adminNotes, onChange: (e) => setAdminNotes(e.target.value), rows: 3, placeholder: "e.g. Reason for suspension, approval notes\u2026", className: "w-full rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500" })] }), _jsx(Toggle, { label: "Verified store", checked: isVerified, onChange: setIsVerified }), _jsx(Toggle, { label: "Featured store", checked: isFeatured, onChange: setIsFeatured }), storeStatus === "suspended" && (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("label", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Suspension reason (optional)" }), _jsx("textarea", { value: suspensionReason, onChange: (e) => setSuspensionReason(e.target.value), rows: 2, placeholder: "e.g. Policy violation, fraudulent activity\u2026", className: "w-full rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500" })] })), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("span", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: ["Capabilities", _jsxs("span", { className: "ml-2 text-xs font-normal text-zinc-500 dark:text-zinc-400", children: ["(", capabilities.size, " active)"] })] }), _jsx("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 divide-y divide-zinc-100 dark:divide-slate-700", children: CAPABILITY_GROUPS.map((group) => {
104
- const checked = group.caps.filter((c) => capabilities.has(c.key)).length;
105
- return (_jsxs("details", { className: "group", children: [_jsxs("summary", { className: "flex cursor-pointer items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wide text-zinc-600 dark:text-zinc-400 select-none hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx("span", { children: group.label }), _jsxs("span", { className: "text-xs font-normal normal-case text-zinc-400 dark:text-zinc-400", children: [checked, "/", group.caps.length] })] }), _jsx("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1.5 px-3 py-2.5 bg-zinc-50/60 dark:bg-slate-800/40", children: group.caps.map((cap) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-xs text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "checkbox", checked: capabilities.has(cap.key), onChange: () => toggleCapability(cap.key), className: "h-3.5 w-3.5 rounded border-zinc-300 dark:border-slate-600 accent-primary" }), cap.label] }, cap.key))) })] }, group.label));
106
- }) })] }), _jsxs(FormActions, { align: "right", children: [_jsx(Button, { type: "button", variant: "secondary", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: !storeId || saveMutation.isPending, children: "Save changes" })] })] }) }));
112
+ }, className: "p-4", children: _jsx(StackedViewShell, { portal: "admin", className: "space-y-4", sections: [
113
+ renderStatusSection,
114
+ renderNotesSection,
115
+ renderTogglesSection,
116
+ renderSuspensionSection,
117
+ renderCapabilitiesSection,
118
+ renderActionsSection,
119
+ ] }) }) }));
107
120
  }
@@ -1,4 +1,3 @@
1
- import type { ListingViewShellProps } from "../../../ui";
2
- export interface AdminStoresViewProps extends ListingViewShellProps {
3
- }
1
+ import type { ListingLayoutProps } from "../../../ui";
2
+ export type AdminStoresViewProps = ListingLayoutProps;
4
3
  export declare function AdminStoresView({ children, ...props }: AdminStoresViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,43 +1,28 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import React, { useState, useCallback } from "react";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React, { useState } from "react";
4
4
  import { useMutation, useQueryClient } from "@tanstack/react-query";
5
- import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
- import { usePanelUrlSync } from "../../../react/hooks/use-panel-url-sync";
7
- import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
8
- import { BulkActionBar, FilterChipGroup, ListingToolbar, Pagination, ListingViewShell, RowActionMenu, useToast, ListingFilterDrawer } from "../../../ui";
9
- import { AdminViewCards } from "./AdminViewCards";
5
+ import { FilterChipGroup, ListingLayout, RowActionMenu, useToast } from "../../../ui";
10
6
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
11
7
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
8
  import { ADMIN_STORE_STATUS_TABS } from "../constants/filter-tabs";
13
- import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } from "../hooks/useAdminListingData";
9
+ import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
10
+ import { DataListingView } from "./DataListingView";
14
11
  import { apiClient } from "../../../http";
15
- import { DataTable } from "./DataTable";
16
12
  import { AdminStoreEditorView } from "./AdminStoreEditorView";
17
- import { useBottomActions } from "../../layout";
18
- const PAGE_SIZE = 25;
19
- const FILTER_KEYS = ["status"];
20
- const DEFAULT_SORT = "-createdAt";
21
- const SORT_OPTIONS = [
22
- { value: "-createdAt", label: "Newest" },
23
- { value: "createdAt", label: "Oldest" },
24
- { value: "storeName", label: "Name A–Z" },
25
- ];
26
- const STATUS_OPTIONS = ADMIN_STORE_STATUS_TABS;
27
13
  export function AdminStoresView({ children, ...props }) {
28
- const hasChildren = React.Children.count(children) > 0;
29
- const [view, setView] = useState("table");
14
+ const [editorRow, setEditorRow] = useState(null);
30
15
  const toast = useToast();
31
16
  const queryClient = useQueryClient();
32
- const table = useUrlTable({ defaults: { pageSize: String(PAGE_SIZE), sort: DEFAULT_SORT } });
33
- const { openEditPanel, closePanel, isEditOpen, editId } = usePanelUrlSync();
34
17
  const verifyStore = useMutation({
35
18
  mutationFn: (storeId) => apiClient.patch(ADMIN_ENDPOINTS.STORE_BY_ID(storeId), { isVerified: true }),
36
19
  onSuccess: () => {
37
20
  toast.showToast("Store verified.", "success");
38
21
  void queryClient.invalidateQueries({ queryKey: ["admin", "stores", "listing"] });
39
22
  },
40
- onError: () => { toast.showToast("Failed to verify store.", "error"); },
23
+ onError: () => {
24
+ toast.showToast("Failed to verify store.", "error");
25
+ },
41
26
  });
42
27
  const suspendStore = useMutation({
43
28
  mutationFn: (storeId) => apiClient.patch(ADMIN_ENDPOINTS.STORE_BY_ID(storeId), { storeStatus: "suspended" }),
@@ -45,47 +30,27 @@ export function AdminStoresView({ children, ...props }) {
45
30
  toast.showToast("Store suspended.", "success");
46
31
  void queryClient.invalidateQueries({ queryKey: ["admin", "stores", "listing"] });
47
32
  },
48
- onError: () => { toast.showToast("Failed to suspend store.", "error"); },
33
+ onError: () => {
34
+ toast.showToast("Failed to suspend store.", "error");
35
+ },
49
36
  });
50
- const [searchInput, setSearchInput] = useState(table.get("q") || "");
51
- const [filterOpen, setFilterOpen] = useState(false);
52
- const [pendingFilters, setPendingFilters] = useState(() => Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
53
- const openFilters = useCallback(() => {
54
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, table.get(k)])));
55
- setFilterOpen(true);
56
- }, [table]);
57
- const applyFilters = useCallback(() => {
58
- const updates = { page: "1" };
59
- for (const k of FILTER_KEYS)
60
- updates[k] = pendingFilters[k] ?? "";
61
- table.setMany(updates);
62
- setFilterOpen(false);
63
- }, [pendingFilters, table]);
64
- const clearFilters = useCallback(() => {
65
- setPendingFilters(Object.fromEntries(FILTER_KEYS.map((k) => [k, ""])));
66
- }, []);
67
- const resetAll = useCallback(() => {
68
- const updates = { q: "", sort: "" };
69
- for (const k of FILTER_KEYS)
70
- updates[k] = "";
71
- table.setMany(updates);
72
- setSearchInput("");
73
- }, [table]);
74
- const commitSearch = useCallback(() => {
75
- table.set("q", searchInput.trim());
76
- }, [searchInput, table]);
77
- const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
78
- const hasActiveState = !!table.get("q") || table.get("sort") !== DEFAULT_SORT || activeFilterCount > 0;
79
- const statusRaw = table.get("status");
80
- const filters = statusRaw && statusRaw !== "All" ? `status==${statusRaw}` : undefined;
81
- const { rows, total, isLoading, errorMessage } = useAdminListingData({
37
+ if (React.Children.count(children) > 0) {
38
+ return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
39
+ }
40
+ const config = {
41
+ portal: "admin",
42
+ title: "Stores",
43
+ searchPlaceholder: "Search stores, slugs, or owner names",
44
+ emptyLabel: "No stores found",
45
+ filterKeys: ["status"],
46
+ defaultSort: "-createdAt",
82
47
  queryKey: ["admin", "stores", "listing"],
83
48
  endpoint: ADMIN_ENDPOINTS.STORES,
84
- page: table.getNumber("page", 1),
85
- pageSize: PAGE_SIZE,
86
- sorts: table.get("sort") || DEFAULT_SORT,
87
- filters,
88
- q: table.get("q") || undefined,
49
+ sortOptions: [
50
+ { value: "-createdAt", label: "Newest" },
51
+ { value: "createdAt", label: "Oldest" },
52
+ { value: "storeName", label: "Name A–Z" },
53
+ ],
89
54
  mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
90
55
  id: toStringValue(item.id, `store-${index}`),
91
56
  primary: toStringValue(item.storeName, "Unnamed store"),
@@ -98,42 +63,45 @@ export function AdminStoresView({ children, ...props }) {
98
63
  _raw: item,
99
64
  })),
100
65
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
101
- });
102
- const currentPage = table.getNumber("page", 1);
103
- const totalPages = Math.ceil(total / PAGE_SIZE);
104
- const panelRow = editId ? (rows.find((r) => r.id === editId) ?? null) : null;
105
- const selection = useBulkSelection({ items: rows, keyExtractor: (r) => r.id });
106
- if (hasChildren) {
107
- return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
108
- }
109
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search stores, slugs, or owner names", 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 }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
110
- { id: "manage", label: ACTIONS.ADMIN["manage-store"].label, variant: "primary", onClick: () => { const id = selection.selectedIds[0]; if (id)
111
- openEditPanel(id); selection.clearSelection(); } },
112
- ] }), 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) }) })), _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 px-4 py-3 text-sm text-error dark:border-red-900/60", children: errorMessage })), view === "table" ? (_jsx(DataTable, { rows: rows, isLoading: isLoading, emptyLabel: "No stores found", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next ? selection.setSelectedIds(rows.map(r => r.id)) : selection.clearSelection(), renderRowActions: (row) => {
113
- const sr = row;
114
- const isSuspended = sr.status?.toLowerCase() === "suspended";
115
- const isVerified = Boolean(sr._raw?.isVerified);
116
- useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
117
- { id: "manage", label: ACTIONS.ADMIN["manage-store"].label, variant: "primary", onClick: () => { const id = selection.selectedIds[0]; if (id)
118
- openEditPanel(id); selection.clearSelection(); } },
119
- ] } } : {});
120
- return (_jsx(RowActionMenu, { actions: [
121
- {
122
- label: ACTIONS.ADMIN["manage-store"].label,
123
- onClick: () => openEditPanel(sr.id),
124
- },
125
- {
126
- label: ACTIONS.ADMIN["verify-store"].label,
127
- onClick: () => verifyStore.mutate(sr.id),
128
- disabled: isVerified || verifyStore.isPending,
129
- },
130
- {
131
- label: ACTIONS.ADMIN["suspend-store"].label,
132
- onClick: () => suspendStore.mutate(sr.id),
133
- disabled: isSuspended || suspendStore.isPending,
134
- },
135
- ] }));
136
- } })) : (_jsx(AdminViewCards, { rows: rows, view: view, isLoading: isLoading, emptyLabel: "No stores found", onRowClick: (row) => openEditPanel(row.id), selectedIdSet: selection.selectedIdSet, onToggleSelect: selection.toggle }))] }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }) })] }), _jsx(AdminStoreEditorView, { open: isEditOpen, onClose: closePanel, storeId: editId ?? undefined, storeName: panelRow?.primary, currentStatus: panelRow?.status?.toLowerCase(), currentIsVerified: Boolean(panelRow?._raw?.isVerified), currentCapabilities: Array.isArray(panelRow?._raw?.capabilities)
137
- ? panelRow._raw.capabilities
66
+ buildFilters: (state) => state.status && state.status !== "All" ? `status==${state.status}` : undefined,
67
+ onRowClick: (row) => setEditorRow(row),
68
+ buildBulkActions: (selection) => [
69
+ {
70
+ id: "manage",
71
+ label: ACTIONS.ADMIN["manage-store"].label,
72
+ variant: "primary",
73
+ onClick: () => {
74
+ const id = selection.selectedIds[0];
75
+ const row = selection.rows.find((r) => r.id === id) ?? null;
76
+ if (row)
77
+ setEditorRow(row);
78
+ selection.clearSelection();
79
+ },
80
+ },
81
+ ],
82
+ renderRowActions: (row) => {
83
+ const isSuspended = row.status?.toLowerCase() === "suspended";
84
+ const isVerified = Boolean(row._raw?.isVerified);
85
+ return (_jsx(RowActionMenu, { actions: [
86
+ {
87
+ label: ACTIONS.ADMIN["manage-store"].label,
88
+ onClick: () => setEditorRow(row),
89
+ },
90
+ {
91
+ label: ACTIONS.ADMIN["verify-store"].label,
92
+ onClick: () => verifyStore.mutate(row.id),
93
+ disabled: isVerified || verifyStore.isPending,
94
+ },
95
+ {
96
+ label: ACTIONS.ADMIN["suspend-store"].label,
97
+ onClick: () => suspendStore.mutate(row.id),
98
+ disabled: isSuspended || suspendStore.isPending,
99
+ },
100
+ ] }));
101
+ },
102
+ renderFilterPanel: ({ pendingFilters, setPendingFilters }) => (_jsx(FilterChipGroup, { label: "Status", tabs: ADMIN_STORE_STATUS_TABS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) })),
103
+ };
104
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(AdminStoreEditorView, { open: Boolean(editorRow), onClose: () => setEditorRow(null), storeId: editorRow?.id, storeName: editorRow?.primary, currentStatus: editorRow?.status?.toLowerCase(), currentIsVerified: Boolean(editorRow?._raw?.isVerified), currentCapabilities: Array.isArray(editorRow?._raw?.capabilities)
105
+ ? editorRow._raw.capabilities
138
106
  : undefined })] }));
139
107
  }
@@ -1,5 +1,5 @@
1
1
  interface AdminSublistingCategoriesViewProps {
2
2
  onBulkDelete?: (ids: string[]) => Promise<void>;
3
3
  }
4
- export declare function AdminSublistingCategoriesView({ onBulkDelete }: AdminSublistingCategoriesViewProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function AdminSublistingCategoriesView({ onBulkDelete, }: AdminSublistingCategoriesViewProps): import("react/jsx-runtime").JSX.Element;
5
5
  export {};