@mohasinac/appkit 2.8.2 → 2.8.4

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 (451) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +7 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
  4. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
  5. package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
  6. package/dist/_internal/client/scaffolds/AppShell.js +2 -1
  7. package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
  8. package/dist/_internal/server/features/checkout/actions.js +40 -39
  9. package/dist/_internal/shared/actions/action-registry.js +6 -0
  10. package/dist/_internal/shared/config/index.d.ts +1 -1
  11. package/dist/_internal/shared/config/schema.d.ts +0 -8
  12. package/dist/client-entry.d.ts +1 -1
  13. package/dist/client.d.ts +3 -1
  14. package/dist/client.js +3 -1
  15. package/dist/configs/next.js +12 -22
  16. package/dist/constants/api-endpoints.d.ts +6 -0
  17. package/dist/constants/api-endpoints.js +2 -0
  18. package/dist/features/about/components/AboutView.js +5 -2
  19. package/dist/features/about/components/FAQPageView.js +3 -3
  20. package/dist/features/about/components/FeesView.js +13 -5
  21. package/dist/features/about/components/HelpPageView.js +9 -5
  22. package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
  23. package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
  24. package/dist/features/about/components/HowOffersWorkView.js +10 -5
  25. package/dist/features/about/components/HowOrdersWorkView.js +10 -5
  26. package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
  27. package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
  28. package/dist/features/about/components/HowReviewsWorkView.js +9 -5
  29. package/dist/features/about/components/PolicyPageView.js +3 -3
  30. package/dist/features/about/components/PublicProfileView.js +11 -4
  31. package/dist/features/about/components/SecurityPrivacyView.js +8 -4
  32. package/dist/features/about/components/ShippingPolicyView.js +3 -2
  33. package/dist/features/about/components/TrackOrderView.js +2 -2
  34. package/dist/features/about/components/UnauthorizedView.js +3 -3
  35. package/dist/features/account/components/AddressBook.js +1 -1
  36. package/dist/features/account/components/AddressForm.js +2 -2
  37. package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
  38. package/dist/features/account/components/AddressInlineSelect.js +78 -0
  39. package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
  40. package/dist/features/account/components/AddressSelectorCreate.js +5 -32
  41. package/dist/features/account/components/AddressesIndexListing.js +3 -3
  42. package/dist/features/account/components/ChatWindow.js +2 -1
  43. package/dist/features/account/components/NotificationBell.js +13 -7
  44. package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
  45. package/dist/features/account/components/UserOffersPanel.js +2 -1
  46. package/dist/features/account/components/UserSidebar.js +11 -7
  47. package/dist/features/account/components/UserSupportView.js +13 -4
  48. package/dist/features/account/components/index.d.ts +2 -0
  49. package/dist/features/account/components/index.js +1 -0
  50. package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
  51. package/dist/features/addresses/repository/addresses.repository.js +13 -0
  52. package/dist/features/admin/components/AdminAdEditorView.js +8 -5
  53. package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
  54. package/dist/features/admin/components/AdminAdsView.js +10 -7
  55. package/dist/features/admin/components/AdminAllEventEntriesView.js +5 -3
  56. package/dist/features/admin/components/AdminBidsView.js +6 -4
  57. package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
  58. package/dist/features/admin/components/AdminBlogView.js +6 -4
  59. package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
  60. package/dist/features/admin/components/AdminBrandsView.js +12 -10
  61. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  62. package/dist/features/admin/components/AdminBundlesView.js +13 -11
  63. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  64. package/dist/features/admin/components/AdminCarouselView.js +6 -6
  65. package/dist/features/admin/components/AdminCartsView.js +6 -4
  66. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  67. package/dist/features/admin/components/AdminCategoriesView.js +12 -10
  68. package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
  69. package/dist/features/admin/components/AdminClassifiedView.js +4 -3
  70. package/dist/features/admin/components/AdminContactEditorView.js +8 -1
  71. package/dist/features/admin/components/AdminContactView.js +6 -4
  72. package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
  73. package/dist/features/admin/components/AdminCouponsView.js +6 -4
  74. package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
  75. package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
  76. package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
  77. package/dist/features/admin/components/AdminFaqsView.js +9 -7
  78. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
  79. package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
  80. package/dist/features/admin/components/AdminFeaturesView.js +5 -4
  81. package/dist/features/admin/components/AdminFilterBar.js +4 -4
  82. package/dist/features/admin/components/AdminGroupedListingsView.js +66 -30
  83. package/dist/features/admin/components/AdminGuideHubView.js +4 -1
  84. package/dist/features/admin/components/AdminHistoryView.js +4 -3
  85. package/dist/features/admin/components/AdminLiveView.js +4 -3
  86. package/dist/features/admin/components/AdminMediaView.js +4 -1
  87. package/dist/features/admin/components/AdminNavigationView.js +7 -4
  88. package/dist/features/admin/components/AdminNewsletterView.js +5 -3
  89. package/dist/features/admin/components/AdminNotificationsView.js +8 -6
  90. package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
  91. package/dist/features/admin/components/AdminOrdersView.js +6 -4
  92. package/dist/features/admin/components/AdminPageHeader.js +5 -2
  93. package/dist/features/admin/components/AdminPayoutsView.js +7 -5
  94. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -9
  95. package/dist/features/admin/components/AdminProductEditorView.js +12 -5
  96. package/dist/features/admin/components/AdminProductsView.js +11 -9
  97. package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
  98. package/dist/features/admin/components/AdminReviewsView.js +10 -8
  99. package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
  100. package/dist/features/admin/components/AdminScammersView.js +11 -9
  101. package/dist/features/admin/components/AdminSectionsView.js +20 -22
  102. package/dist/features/admin/components/AdminSessionsManager.js +2 -1
  103. package/dist/features/admin/components/AdminSessionsView.js +8 -6
  104. package/dist/features/admin/components/AdminSidebar.js +11 -7
  105. package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
  106. package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
  107. package/dist/features/admin/components/AdminStoreAddressesView.js +4 -3
  108. package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminStoresView.js +6 -4
  110. package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -5
  111. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
  112. package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
  113. package/dist/features/admin/components/AdminSupportTicketsView.js +11 -9
  114. package/dist/features/admin/components/AdminTeamView.js +6 -4
  115. package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
  116. package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
  117. package/dist/features/admin/components/AdminUsersView.js +6 -4
  118. package/dist/features/admin/components/AdminViewCards.js +12 -6
  119. package/dist/features/admin/components/AdminWishlistsView.js +4 -3
  120. package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
  121. package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
  122. package/dist/features/admin/components/DashboardStats.js +9 -3
  123. package/dist/features/admin/components/DataListingView.js +3 -3
  124. package/dist/features/admin/components/DataTable.js +11 -7
  125. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  126. package/dist/features/admin/components/QuickEditMenu.js +2 -1
  127. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
  128. package/dist/features/admin/constants/filter-tabs.d.ts +1 -1
  129. package/dist/features/admin/constants/filter-tabs.js +0 -11
  130. package/dist/features/admin/types/index.d.ts +1 -1
  131. package/dist/features/auctions/actions/bid-actions.js +4 -2
  132. package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
  133. package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
  134. package/dist/features/auctions/components/AuctionsListView.js +7 -6
  135. package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
  136. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
  137. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
  138. package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
  139. package/dist/features/auth/components/RegisterForm.js +2 -2
  140. package/dist/features/auth/components/VerifyEmailView.js +5 -2
  141. package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
  142. package/dist/features/blog/actions/blog-actions.js +3 -2
  143. package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
  144. package/dist/features/blog/components/BlogIndexListing.js +11 -5
  145. package/dist/features/blog/components/BlogListView.js +11 -3
  146. package/dist/features/blog/components/BlogPostView.js +10 -3
  147. package/dist/features/cart/components/CartDrawer.js +11 -3
  148. package/dist/features/cart/components/CartSummary.js +2 -2
  149. package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
  150. package/dist/features/categories/components/BrandDetailPageView.js +15 -10
  151. package/dist/features/categories/components/BrandDetailTabs.js +5 -1
  152. package/dist/features/categories/components/BundleDetailView.js +6 -3
  153. package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
  154. package/dist/features/categories/components/BundleItemsPicker.js +10 -3
  155. package/dist/features/categories/components/CategoriesIndexListing.js +13 -7
  156. package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
  157. package/dist/features/categories/components/CategoryBundlesListing.js +10 -6
  158. package/dist/features/categories/components/CategoryDetailPageView.js +18 -12
  159. package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
  160. package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
  161. package/dist/features/categories/components/CategoryFilters.js +13 -12
  162. package/dist/features/categories/components/CategoryForm.js +6 -3
  163. package/dist/features/categories/components/CategoryGrid.js +9 -2
  164. package/dist/features/categories/components/CategoryProductsListing.js +10 -4
  165. package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
  166. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  167. package/dist/features/categories/components/CategoryStoresListing.js +3 -3
  168. package/dist/features/categories/components/CategoryTableColumns.js +10 -6
  169. package/dist/features/categories/components/CategoryTree.d.ts +1 -1
  170. package/dist/features/categories/components/CategoryTree.js +2 -2
  171. package/dist/features/categories/schemas/firestore.d.ts +2 -2
  172. package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
  173. package/dist/features/checkout/actions/checkout-actions.js +1 -1
  174. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  175. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  176. package/dist/features/classified/components/ClassifiedListView.js +6 -5
  177. package/dist/features/collections/components/CollectionCard.js +2 -1
  178. package/dist/features/contact/components/ContactForm.js +4 -2
  179. package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
  180. package/dist/features/copilot/components/AdminCopilotView.js +13 -5
  181. package/dist/features/cron/jobs/auction-expiry.job.d.ts +2 -2
  182. package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
  183. package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
  184. package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
  185. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
  186. package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
  187. package/dist/features/events/actions/event-actions.js +6 -4
  188. package/dist/features/events/components/AdminEventEditorView.js +63 -41
  189. package/dist/features/events/components/AdminEventEntriesView.js +9 -6
  190. package/dist/features/events/components/AdminEventsView.js +7 -5
  191. package/dist/features/events/components/EventCard.js +7 -1
  192. package/dist/features/events/components/EventFilters.d.ts +4 -4
  193. package/dist/features/events/components/EventFilters.js +2 -2
  194. package/dist/features/events/components/EventFormDrawer.js +2 -1
  195. package/dist/features/events/components/EventLeaderboard.js +4 -4
  196. package/dist/features/events/components/EventOfferCard.js +4 -1
  197. package/dist/features/events/components/EventParticipateView.js +3 -2
  198. package/dist/features/events/components/EventPollWidget.js +6 -5
  199. package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
  200. package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
  201. package/dist/features/events/components/EventRafflesSection.js +6 -4
  202. package/dist/features/events/components/EventSaleBanner.js +5 -2
  203. package/dist/features/events/components/EventsIndexListing.js +8 -2
  204. package/dist/features/events/components/EventsListView.js +4 -1
  205. package/dist/features/events/components/SpinWheelView.js +7 -2
  206. package/dist/features/events/schemas/firestore.d.ts +1 -0
  207. package/dist/features/events/types/index.d.ts +1 -0
  208. package/dist/features/faq/actions/faq-actions.js +4 -2
  209. package/dist/features/faq/components/ContactCTA.js +4 -1
  210. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  211. package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
  212. package/dist/features/faq/components/FAQPageContent.js +7 -6
  213. package/dist/features/faq/components/FAQSortDropdown.js +2 -2
  214. package/dist/features/filters/AsyncFacetSection.js +4 -2
  215. package/dist/features/filters/FilterFacetSection.js +14 -6
  216. package/dist/features/filters/RangeFilter.js +4 -2
  217. package/dist/features/filters/SwitchFilter.js +2 -1
  218. package/dist/features/forms/Checkbox.js +1 -1
  219. package/dist/features/forms/Radio.js +1 -1
  220. package/dist/features/forms/Slider.js +1 -1
  221. package/dist/features/homepage/components/AdSlot.js +4 -4
  222. package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
  223. package/dist/features/homepage/components/AnnouncementBar.js +2 -1
  224. package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
  225. package/dist/features/homepage/components/BrandsSection.js +6 -3
  226. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  227. package/dist/features/homepage/components/CharacterHotspot.js +5 -2
  228. package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
  229. package/dist/features/homepage/components/CustomCardsSection.js +13 -7
  230. package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
  231. package/dist/features/homepage/components/FAQSection.js +7 -4
  232. package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
  233. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  234. package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
  235. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  236. package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
  237. package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
  238. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  239. package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -2
  240. package/dist/features/homepage/components/NewsletterBanner.js +3 -2
  241. package/dist/features/homepage/components/NewsletterSection.js +5 -2
  242. package/dist/features/homepage/components/PromoGrid.js +4 -1
  243. package/dist/features/homepage/components/SectionCarousel.js +7 -4
  244. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
  245. package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
  246. package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
  247. package/dist/features/homepage/components/SocialFeedSection.js +4 -4
  248. package/dist/features/homepage/components/SocialPostCard.js +6 -3
  249. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  250. package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
  251. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  252. package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
  253. package/dist/features/layout/AppLayoutShell.js +2 -1
  254. package/dist/features/layout/BackToTop.js +1 -1
  255. package/dist/features/layout/BottomActions.js +4 -30
  256. package/dist/features/layout/BottomActionsContext.d.ts +0 -36
  257. package/dist/features/layout/BottomActionsContext.js +0 -36
  258. package/dist/features/layout/BottomNavItem.js +1 -1
  259. package/dist/features/layout/BottomSheet.js +4 -1
  260. package/dist/features/layout/FooterLayout.js +1 -1
  261. package/dist/features/layout/NavbarLayout.js +4 -1
  262. package/dist/features/layout/SidebarLayout.js +5 -2
  263. package/dist/features/live/components/LiveItemFilters.js +2 -2
  264. package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
  265. package/dist/features/live/components/LiveItemsListView.js +6 -5
  266. package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
  267. package/dist/features/media/AvatarUpload.js +2 -2
  268. package/dist/features/media/MediaLightbox.js +3 -2
  269. package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
  270. package/dist/features/media/modals/VideoTrimModal.js +1 -1
  271. package/dist/features/media/upload/CameraCapture.js +1 -1
  272. package/dist/features/media/upload/ImageUpload.js +4 -1
  273. package/dist/features/media/upload/MediaUploadField.js +11 -2
  274. package/dist/features/media/upload/MediaUploadList.js +5 -1
  275. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  276. package/dist/features/orders/components/OrdersList.js +2 -1
  277. package/dist/features/orders/components/RefundHistoryTable.js +4 -1
  278. package/dist/features/orders/components/RefundRequestView.js +2 -1
  279. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
  280. package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
  281. package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
  282. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
  283. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
  284. package/dist/features/pre-orders/components/PreOrdersListView.js +5 -4
  285. package/dist/features/products/actions/product-actions.js +17 -15
  286. package/dist/features/products/columns/index.d.ts +1 -1
  287. package/dist/features/products/columns/index.js +1 -1
  288. package/dist/features/products/columns/productTableColumns.js +9 -4
  289. package/dist/features/products/components/AuctionsIndexListing.js +9 -3
  290. package/dist/features/products/components/BidHistory.js +4 -4
  291. package/dist/features/products/components/CompareOverlay.js +10 -2
  292. package/dist/features/products/components/CustomFieldsEditor.js +2 -1
  293. package/dist/features/products/components/CustomSectionTabContent.js +2 -2
  294. package/dist/features/products/components/CustomSectionsEditor.js +3 -2
  295. package/dist/features/products/components/GroupSettingsPanel.js +34 -26
  296. package/dist/features/products/components/MakeOfferButton.js +6 -2
  297. package/dist/features/products/components/MakeOfferForm.js +2 -1
  298. package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
  299. package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
  300. package/dist/features/products/components/PlaceBidForm.js +2 -1
  301. package/dist/features/products/components/PrizeDrawCollage.js +6 -16
  302. package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
  303. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
  304. package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
  305. package/dist/features/products/components/PrizeDrawsListingView.js +5 -4
  306. package/dist/features/products/components/PrizeDrawsSection.js +6 -4
  307. package/dist/features/products/components/PrizeRevealModal.js +5 -1
  308. package/dist/features/products/components/ProductDetailPageView.js +32 -16
  309. package/dist/features/products/components/ProductFeatureBadges.js +9 -9
  310. package/dist/features/products/components/ProductForm.d.ts +11 -1
  311. package/dist/features/products/components/ProductForm.js +10 -5
  312. package/dist/features/products/components/ProductGalleryClient.js +8 -4
  313. package/dist/features/products/components/ProductGradingTab.js +4 -1
  314. package/dist/features/products/components/ProductGrid.js +35 -14
  315. package/dist/features/products/components/ProductInfo.js +2 -1
  316. package/dist/features/products/components/ProductTabs.js +2 -1
  317. package/dist/features/products/components/ProductTabsShell.js +5 -1
  318. package/dist/features/products/components/ProductsIndexListing.js +32 -24
  319. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  320. package/dist/features/products/components/RelatedProducts.js +3 -3
  321. package/dist/features/products/components/ShowGroupSection.js +10 -6
  322. package/dist/features/products/components/SublistingCarouselSection.js +7 -3
  323. package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
  324. package/dist/features/products/components/SublistingCategorySelect.js +4 -37
  325. package/dist/features/products/constants/action-defs.js +3 -3
  326. package/dist/features/products/constants/sieve.d.ts +2 -2
  327. package/dist/features/products/constants/sieve.js +2 -2
  328. package/dist/features/products/hooks/useRelatedProducts.js +5 -4
  329. package/dist/features/promotions/components/CouponCard.js +5 -3
  330. package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
  331. package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
  332. package/dist/features/promotions/repository/coupons.repository.js +2 -0
  333. package/dist/features/reviews/actions/review-actions.js +2 -1
  334. package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
  335. package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
  336. package/dist/features/reviews/components/ReviewSummary.js +4 -2
  337. package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
  338. package/dist/features/reviews/components/ReviewsIndexPageView.js +7 -6
  339. package/dist/features/reviews/components/ReviewsList.js +1 -1
  340. package/dist/features/scams/actions/scam-actions.js +3 -2
  341. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  342. package/dist/features/scams/components/ScamProfileView.js +3 -3
  343. package/dist/features/scams/components/ScamRegistryView.js +11 -8
  344. package/dist/features/search/actions/search-actions.js +7 -6
  345. package/dist/features/search/components/Search.js +9 -6
  346. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  347. package/dist/features/search/components/SearchResultsSection.js +1 -1
  348. package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
  349. package/dist/features/seller/components/CouponInlineSelect.js +104 -0
  350. package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
  351. package/dist/features/seller/components/GroupInlineSelect.js +80 -0
  352. package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
  353. package/dist/features/seller/components/PrintCenterView.js +2 -1
  354. package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
  355. package/dist/features/seller/components/ProductInlineSelect.js +42 -0
  356. package/dist/features/seller/components/QuickProductForm.js +4 -1
  357. package/dist/features/seller/components/SellerAddressesView.js +8 -3
  358. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
  359. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  360. package/dist/features/seller/components/SellerAuctionsView.js +7 -5
  361. package/dist/features/seller/components/SellerBidsView.js +12 -10
  362. package/dist/features/seller/components/SellerBundlesView.js +9 -7
  363. package/dist/features/seller/components/SellerClassifiedView.js +6 -5
  364. package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
  365. package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
  366. package/dist/features/seller/components/SellerCouponsView.js +7 -5
  367. package/dist/features/seller/components/SellerDashboardView.js +2 -2
  368. package/dist/features/seller/components/SellerDigitalCodesView.js +7 -6
  369. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  370. package/dist/features/seller/components/SellerGroupedListingsView.js +10 -9
  371. package/dist/features/seller/components/SellerLiveView.js +6 -5
  372. package/dist/features/seller/components/SellerOffersView.js +6 -4
  373. package/dist/features/seller/components/SellerOrdersView.js +18 -13
  374. package/dist/features/seller/components/SellerPayoutMethodsView.js +8 -6
  375. package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
  376. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
  377. package/dist/features/seller/components/SellerPayoutsView.js +6 -4
  378. package/dist/features/seller/components/SellerPreOrdersView.js +12 -10
  379. package/dist/features/seller/components/SellerPrizeDrawsView.js +12 -10
  380. package/dist/features/seller/components/SellerProductShell.js +1 -1
  381. package/dist/features/seller/components/SellerProductsCards.js +4 -1
  382. package/dist/features/seller/components/SellerProductsView.js +14 -12
  383. package/dist/features/seller/components/SellerReviewsView.js +7 -3
  384. package/dist/features/seller/components/SellerShippingConfigsView.js +7 -6
  385. package/dist/features/seller/components/SellerShippingView.js +1 -1
  386. package/dist/features/seller/components/SellerSidebar.js +15 -8
  387. package/dist/features/seller/components/SellerStoreCategoriesView.js +5 -4
  388. package/dist/features/seller/components/SellerStorefrontView.js +2 -2
  389. package/dist/features/seller/components/SellerTemplatesView.js +11 -7
  390. package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
  391. package/dist/features/seller/components/SublistingInlineSelect.js +84 -0
  392. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  393. package/dist/features/seller/components/index.d.ts +8 -0
  394. package/dist/features/seller/components/index.js +4 -0
  395. package/dist/features/shell/FormShell.js +10 -2
  396. package/dist/features/shell/QuickFormDrawer.js +5 -5
  397. package/dist/features/shell/StepForm.js +6 -6
  398. package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
  399. package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
  400. package/dist/features/stores/actions/store-query-actions.js +3 -2
  401. package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
  402. package/dist/features/stores/components/StoreAboutView.js +4 -1
  403. package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
  404. package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
  405. package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
  406. package/dist/features/stores/components/StoreAuctionsPageView.js +4 -2
  407. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  408. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
  409. package/dist/features/stores/components/StoreGuideHubView.js +5 -2
  410. package/dist/features/stores/components/StoreHeader.js +8 -1
  411. package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
  412. package/dist/features/stores/components/StorePreOrdersPageView.js +4 -2
  413. package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
  414. package/dist/features/stores/components/StoreProductsListing.js +6 -3
  415. package/dist/features/stores/components/StoreProductsPageView.js +2 -1
  416. package/dist/features/stores/components/StoreProductsView.js +5 -4
  417. package/dist/features/stores/components/StoreReviewsListing.js +8 -2
  418. package/dist/features/stores/components/StoresIndexListing.js +16 -9
  419. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
  420. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
  421. package/dist/features/wishlist/components/WishlistPage.js +2 -1
  422. package/dist/features/wishlist/components/WishlistView.js +4 -3
  423. package/dist/index.d.ts +10 -0
  424. package/dist/index.js +13 -1
  425. package/dist/next/components/GlobalError.js +2 -2
  426. package/dist/next/routing/route-map.d.ts +2 -0
  427. package/dist/next/routing/route-map.js +1 -0
  428. package/dist/react/ErrorBoundary.js +2 -2
  429. package/dist/styles.css +2 -1
  430. package/dist/tailwind-utilities.css +1 -1
  431. package/dist/ui/DataTable.js +17 -16
  432. package/dist/ui/components/DateInput.js +2 -2
  433. package/dist/ui/components/DetailPageGallery.js +4 -1
  434. package/dist/ui/components/DetailPageTabs.js +6 -2
  435. package/dist/ui/components/ImageLightbox.js +5 -3
  436. package/dist/ui/components/Input.js +6 -3
  437. package/dist/ui/components/Layout.d.ts +4 -0
  438. package/dist/ui/components/Layout.js +1 -1
  439. package/dist/ui/components/Layout.style.css +1 -0
  440. package/dist/ui/components/ListingFilterDrawer.js +4 -1
  441. package/dist/ui/components/ListingLayout.js +9 -8
  442. package/dist/ui/components/ListingToolbar.js +5 -1
  443. package/dist/ui/components/PaginatedSelect.d.ts +1 -2
  444. package/dist/ui/components/PaginatedSelect.js +1 -2
  445. package/dist/ui/components/Radio.js +1 -1
  446. package/dist/ui/components/Select.js +2 -1
  447. package/dist/ui/components/Slider.js +1 -1
  448. package/dist/ui/components/VacationBanner.js +2 -1
  449. package/dist/ui/components/surface-tokens.d.ts +1 -0
  450. package/dist/ui/components/surface-tokens.js +1 -0
  451. package/package.json +11 -2
@@ -1,5 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
4
+ import { sortBy } from "@mohasinac/appkit";
3
5
  import React, { useCallback } from "react";
4
6
  import { useQueryClient } from "@tanstack/react-query";
5
7
  import { Div, FilterChipGroup, ListingLayout, Text, useToast } from "../../../ui";
@@ -47,12 +49,12 @@ export function AdminCouponsView({ children, onBulkArchive, onBulkDelete, ...pro
47
49
  searchPlaceholder: "Search codes, campaigns, or seller scopes",
48
50
  emptyLabel: "No coupons found",
49
51
  filterKeys: ["type"],
50
- defaultSort: "-createdAt",
52
+ defaultSort: sortBy("createdAt", "DESC"),
51
53
  queryKey: ["admin", "coupons", "listing"],
52
54
  endpoint: ADMIN_ENDPOINTS.COUPONS,
53
55
  sortOptions: [
54
- { value: "-createdAt", label: "Newest" },
55
- { value: "createdAt", label: "Oldest" },
56
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
57
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
56
58
  { value: "code", label: "Code A–Z" },
57
59
  ],
58
60
  hideTableView: true,
@@ -61,7 +63,7 @@ export function AdminCouponsView({ children, onBulkArchive, onBulkDelete, ...pro
61
63
  raw: item,
62
64
  })),
63
65
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
64
- buildFilters: (state) => state.type && state.type !== "All" ? `type==${state.type}` : undefined,
66
+ buildFilters: (state) => state.type && state.type !== "All" ? sieveFilter("type", SIEVE_OP.EQ, state.type) : undefined,
65
67
  primaryAction: {
66
68
  label: "Add Coupon",
67
69
  onClick: ({ openCreatePanel }) => openCreatePanel(),
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  /**
4
4
  * AdminDigitalCodesView — admin browse of digital-code listings (W1-29).
5
5
  */
6
+ import { sortBy } from "@mohasinac/appkit";
6
7
  import React from "react";
7
8
  import { ListingLayout } from "../../../ui";
8
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -14,12 +15,12 @@ const ADMIN_DIGITAL_CODES_CONFIG = {
14
15
  searchPlaceholder: "Search digital code listings",
15
16
  emptyLabel: "No digital code listings",
16
17
  filterKeys: [],
17
- defaultSort: "-createdAt",
18
+ defaultSort: sortBy("createdAt", "DESC"),
18
19
  queryKey: ["admin", "digital-codes", "listing"],
19
20
  endpoint: ADMIN_ENDPOINTS.PRODUCTS,
20
21
  sortOptions: [
21
- { value: "-createdAt", label: "Newest" },
22
- { value: "createdAt", label: "Oldest" },
22
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
23
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
23
24
  { value: "title", label: "Title A–Z" },
24
25
  ],
25
26
  mapRows: (response) => toRecordArray(response.items).map((item, index) => {
@@ -2,10 +2,13 @@
2
2
  import { jsxs as _jsxs, jsx as _jsx, 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, ConfirmDeleteModal, Form, FormActions, Select, SideDrawer, Text, useToast } from "../../../ui";
5
+ import { Button, ConfirmDeleteModal, Div, Form, FormActions, Label, Select, SideDrawer, Span, Text, useToast } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
8
  import { PERMISSION_GROUPS, } from "../../auth/permissions/constants";
9
+ const __O = {
10
+ yAuto: "overflow-y-auto",
11
+ };
9
12
  // --- Helpers -----------------------------------------------------------------
10
13
  const GROUP_OPTIONS = [
11
14
  { label: "Content Moderator", value: "content_moderator" },
@@ -70,12 +73,12 @@ function formatPermLabel(perm) {
70
73
  .replace(/\b\w/g, (c) => c.toUpperCase());
71
74
  }
72
75
  function PermissionDomainsPanel({ permissions, togglePerm }) {
73
- return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("span", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: ["Permissions", _jsxs("span", { className: "ml-2 text-xs font-normal text-zinc-500 dark:text-zinc-400", children: ["(", permissions.size, " selected)"] })] }), _jsx("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 divide-y divide-zinc-100 dark:divide-slate-700 max-h-[42vh] overflow-y-auto", children: PERMISSION_DOMAINS.map((domain) => {
76
+ return (_jsxs(Div, { className: "flex flex-col gap-2", children: [_jsxs(Span, { size: "sm", weight: "medium", className: "text-zinc-700 dark:text-zinc-300", children: ["Permissions", _jsxs(Span, { size: "xs", weight: "normal", className: "ml-2 text-zinc-500 dark:text-zinc-400", children: ["(", permissions.size, " selected)"] })] }), _jsx(Div, { className: `rounded-xl border border-zinc-200 dark:border-slate-700 divide-y divide-zinc-100 dark:divide-slate-700 max-h-[42vh] ${__O.yAuto}`, children: PERMISSION_DOMAINS.map((domain) => {
74
77
  const domainPerms = getPermissionsForDomain(domain.prefix);
75
78
  if (domainPerms.length === 0)
76
79
  return null;
77
80
  const checked = domainPerms.filter((p) => permissions.has(p)).length;
78
- 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: domain.label }), _jsxs("span", { className: "text-xs font-normal normal-case text-zinc-400 dark:text-zinc-400", children: [checked, "/", domainPerms.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: domainPerms.map((perm) => (_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: permissions.has(perm), onChange: () => togglePerm(perm), className: "h-3.5 w-3.5 rounded border-zinc-300 dark:border-slate-600 accent-primary" }), formatPermLabel(perm)] }, perm))) })] }, domain.prefix));
81
+ return (_jsxs("details", { className: "group", children: [_jsxs("summary", { className: "flex cursor-pointer items-center justify-between px-3 py-2 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, { size: "xs", children: domain.label }), _jsxs(Span, { size: "xs", weight: "normal", className: "normal-case text-zinc-400 dark:text-zinc-400", children: [checked, "/", domainPerms.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: domainPerms.map((perm) => (_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: permissions.has(perm), onChange: () => togglePerm(perm), className: "h-3.5 w-3.5 rounded border-zinc-300 dark:border-slate-600 accent-primary" }), formatPermLabel(perm)] }, perm))) })] }, domain.prefix));
79
82
  }) })] }));
80
83
  }
81
84
  // --- Component ---------------------------------------------------------------
@@ -167,5 +170,5 @@ export function AdminEmployeeEditorView({ open, onClose, mode, userId, displayNa
167
170
  else
168
171
  updateMutation.mutate();
169
172
  };
170
- return (_jsxs(_Fragment, { children: [_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: mode === "invite" ? "Invite Employee" : `Edit — ${displayName ?? "Employee"}`, children: _jsxs(Form, { onSubmit: handleSubmit, className: "flex flex-col gap-5 p-4", children: [mode === "invite" && (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("label", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Email address" }), _jsx("input", { type: "email", required: true, value: email, onChange: (e) => setEmail(e.target.value), placeholder: "employee@example.com", className: "rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-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/60 transition" })] })), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("label", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Permission group" }), _jsx(Select, { value: group, onChange: (e) => applyGroupPreset(e.target.value), options: GROUP_OPTIONS }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Selecting a group auto-fills the permissions below. You can still customise individual permissions." })] }), _jsx(PermissionDomainsPanel, { permissions: permissions, togglePerm: togglePerm }), _jsxs(FormActions, { children: [_jsx(Button, { type: "submit", variant: "primary", disabled: isBusy, isLoading: isBusy, children: mode === "invite" ? "Send Invite" : "Save" }), mode === "edit" && userId && (_jsx(Button, { type: "button", variant: "danger", disabled: isBusy, onClick: () => setRevokeOpen(true), children: "Revoke Access" }))] })] }) }), mode === "edit" && (_jsx(ConfirmDeleteModal, { isOpen: revokeOpen, onClose: () => setRevokeOpen(false), onConfirm: () => revokeMutation.mutate(), isDeleting: revokeMutation.isPending, title: "Revoke employee access?", message: `${displayName ?? "This employee"} will lose admin panel access immediately. Their user account remains active — only their role is reset to user.`, confirmText: "Revoke Access", variant: "danger" }))] }));
173
+ return (_jsxs(_Fragment, { children: [_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: mode === "invite" ? "Invite Employee" : `Edit — ${displayName ?? "Employee"}`, children: _jsxs(Form, { onSubmit: handleSubmit, className: "flex flex-col gap-5 p-4", children: [mode === "invite" && (_jsxs(Div, { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Email address" }), _jsx("input", { type: "email", required: true, value: email, onChange: (e) => setEmail(e.target.value), placeholder: "employee@example.com", className: "rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-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/60 transition" })] })), _jsxs(Div, { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Permission group" }), _jsx(Select, { value: group, onChange: (e) => applyGroupPreset(e.target.value), options: GROUP_OPTIONS }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Selecting a group auto-fills the permissions below. You can still customise individual permissions." })] }), _jsx(PermissionDomainsPanel, { permissions: permissions, togglePerm: togglePerm }), _jsxs(FormActions, { children: [_jsx(Button, { type: "submit", variant: "primary", disabled: isBusy, isLoading: isBusy, children: mode === "invite" ? "Send Invite" : "Save" }), mode === "edit" && userId && (_jsx(Button, { type: "button", variant: "danger", disabled: isBusy, onClick: () => setRevokeOpen(true), children: "Revoke Access" }))] })] }) }), mode === "edit" && (_jsx(ConfirmDeleteModal, { isOpen: revokeOpen, onClose: () => setRevokeOpen(false), onConfirm: () => revokeMutation.mutate(), isDeleting: revokeMutation.isPending, title: "Revoke employee access?", message: `${displayName ?? "This employee"} will lose admin panel access immediately. Their user account remains active — only their role is reset to user.`, confirmText: "Revoke Access", variant: "danger" }))] }));
171
174
  }
@@ -2,10 +2,16 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { useMutation, useQuery } from "@tanstack/react-query";
5
- import { Button, ConfirmDeleteModal, Form, Input, RichTextEditor, Select, StackedViewShell, TagInput, Text, Toggle, useToast } from "../../../ui";
5
+ import { Button, ConfirmDeleteModal, Div, Form, Input, RichTextEditor, Select, StackedViewShell, TagInput, Text, Toggle, useToast } from "../../../ui";
6
6
  import { FieldInput, FormShellContext, useFormShellState } from "../../../ui/forms";
7
7
  import { apiClient } from "../../../http";
8
8
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
+ const __P = {
10
+ p4: "p-4",
11
+ };
12
+ const __O = {
13
+ yAuto: "overflow-y-auto",
14
+ };
9
15
  // --- Constants ---------------------------------------------------------------
10
16
  const CATEGORY_OPTIONS = [
11
17
  { label: "Shipping", value: "shipping" },
@@ -126,9 +132,9 @@ export function AdminFaqEditorView({ faqId, onSaved, onDeleted, embedded, ...res
126
132
  }, className: "space-y-5", children: [_jsx(FieldInput, { name: "question", label: "Question", value: question, onChange: (v) => handleQuestionChange(v), required: true, placeholder: "e.g. How does bidding work on LetItRip?" }), _jsx(Input, { label: "Slug", value: slug, onChange: (e) => {
127
133
  setSlug(e.target.value);
128
134
  setSlugManual(true);
129
- }, placeholder: "faq-how-does-bidding-work", helperText: "Auto-generated from question. Must start with 'faq-'." }), _jsxs("div", { className: "space-y-1", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Answer" }), _jsx(RichTextEditor, { value: answer, onChange: setAnswer, placeholder: "Write a clear, helpful answer...", minHeightClassName: "min-h-[200px]" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(Select, { label: "Category", options: CATEGORY_OPTIONS, value: category, onValueChange: setCategory }), _jsx(Input, { label: "Display order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower = shown first within category." })] }), _jsx(Input, { label: "Priority", value: String(priority), onChange: (e) => setPriority(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Higher priority FAQs appear first in search results." }), _jsx(TagInput, { label: "Tags", value: tags, onChange: setTags, placeholder: "e.g. shipping, pokemon, returns" }), _jsxs("div", { className: "space-y-3 rounded-lg border border-zinc-200 dark:border-zinc-700 p-4", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Visibility" }), _jsx(Toggle, { label: "Active (visible to users)", checked: isActive, onChange: setIsActive }), _jsx(Toggle, { label: "Pinned (always shown at top)", checked: isPinned, onChange: setIsPinned }), _jsx(Toggle, { label: "Show on homepage FAQ section", checked: showOnHomepage, onChange: setShowOnHomepage }), _jsx(Toggle, { label: "Show in footer FAQ links", checked: showInFooter, onChange: setShowInFooter })] }), _jsxs("div", { className: "flex gap-3 pt-2", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !canSave || isSubmitting, children: isEdit ? "Save changes" : "Create FAQ" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteConfirmOpen(true), children: "Delete FAQ" }))] })] }, "faq-form"), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete FAQ", message: "Delete this FAQ? This cannot be undone.", onConfirm: () => { deleteMutation.mutate(); setDeleteConfirmOpen(false); }, onClose: () => setDeleteConfirmOpen(false), isDeleting: deleteMutation.isPending }))] }));
135
+ }, placeholder: "faq-how-does-bidding-work", helperText: "Auto-generated from question. Must start with 'faq-'." }), _jsxs(Div, { className: "space-y-1", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Answer" }), _jsx(RichTextEditor, { value: answer, onChange: setAnswer, placeholder: "Write a clear, helpful answer...", minHeightClassName: "min-h-[200px]" })] }), _jsxs(Div, { className: "grid grid-cols-2 gap-4", children: [_jsx(Select, { label: "Category", options: CATEGORY_OPTIONS, value: category, onValueChange: setCategory }), _jsx(Input, { label: "Display order", value: String(order), onChange: (e) => setOrder(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Lower = shown first within category." })] }), _jsx(Input, { label: "Priority", value: String(priority), onChange: (e) => setPriority(parseInt(e.target.value, 10) || 0), type: "number", min: 0, helperText: "Higher priority FAQs appear first in search results." }), _jsx(TagInput, { label: "Tags", value: tags, onChange: setTags, placeholder: "e.g. shipping, pokemon, returns" }), _jsxs(Div, { className: `space-y-3 rounded-lg border border-zinc-200 dark:border-zinc-700 ${__P.p4}`, children: [_jsx(Text, { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Visibility" }), _jsx(Toggle, { label: "Active (visible to users)", checked: isActive, onChange: setIsActive }), _jsx(Toggle, { label: "Pinned (always shown at top)", checked: isPinned, onChange: setIsPinned }), _jsx(Toggle, { label: "Show on homepage FAQ section", checked: showOnHomepage, onChange: setShowOnHomepage }), _jsx(Toggle, { label: "Show in footer FAQ links", checked: showInFooter, onChange: setShowInFooter })] }), _jsxs(Div, { className: "flex gap-3 pt-2", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: !canSave || isSubmitting, children: isEdit ? "Save changes" : "Create FAQ" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteConfirmOpen(true), children: "Delete FAQ" }))] })] }, "faq-form"), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete FAQ", message: "Delete this FAQ? This cannot be undone.", onConfirm: () => { deleteMutation.mutate(); setDeleteConfirmOpen(false); }, onClose: () => setDeleteConfirmOpen(false), isDeleting: deleteMutation.isPending }))] }));
130
136
  if (embedded) {
131
- return _jsx("div", { className: "overflow-y-auto p-4", children: formSection });
137
+ return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formSection });
132
138
  }
133
139
  return (_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit FAQ" : "New FAQ", sections: [formSection] }));
134
140
  }
@@ -1,7 +1,9 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
4
+ import { sortBy } from "@mohasinac/appkit";
3
5
  import React, { useMemo } from "react";
4
- import { Heading, ListingLayout, Span, Text } from "../../../ui";
6
+ import { Div, Heading, ListingLayout, Span, Text } from "../../../ui";
5
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
6
8
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
7
9
  import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
@@ -13,13 +15,13 @@ const COLUMNS = [
13
15
  key: "primary",
14
16
  header: "Question",
15
17
  sortable: true,
16
- render: (row) => (_jsxs("div", { className: "space-y-1", children: [_jsx(Text, { className: "font-semibold text-zinc-900 dark:text-zinc-100", children: row.primary }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: row.secondary })] })),
18
+ render: (row) => (_jsxs(Div, { className: "space-y-1", children: [_jsx(Text, { className: "font-semibold text-zinc-900 dark:text-zinc-100", children: row.primary }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: row.secondary })] })),
17
19
  },
18
20
  {
19
21
  key: "status",
20
22
  header: "Status",
21
23
  className: "w-32",
22
- render: (row) => (_jsx(Span, { className: "inline-flex rounded-full bg-primary-50 px-2.5 py-1 text-xs font-medium text-primary-800 dark:bg-secondary-900/30 dark:text-secondary-300", children: row.status })),
24
+ render: (row) => (_jsx(Span, { size: "xs", weight: "medium", className: "inline-flex rounded-full bg-primary-50 px-2.5 py-1 text-primary-800 dark:bg-secondary-900/30 dark:text-secondary-300", children: row.status })),
23
25
  },
24
26
  {
25
27
  key: "updatedAt",
@@ -35,12 +37,12 @@ export function AdminFaqsView({ children, onBulkArchive, onBulkDelete, ...props
35
37
  searchPlaceholder: "Search questions, categories, or tokens",
36
38
  emptyLabel: "No FAQs found",
37
39
  filterKeys: ["isActive"],
38
- defaultSort: "priority",
40
+ defaultSort: sortBy("priority", "ASC"),
39
41
  queryKey: ["admin", "faqs", "listing"],
40
42
  endpoint: ADMIN_ENDPOINTS.FAQS,
41
43
  sortOptions: [
42
44
  { value: "priority", label: "Priority" },
43
- { value: "-createdAt", label: "Newest" },
45
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
44
46
  { value: "question", label: "Question A–Z" },
45
47
  ],
46
48
  columns: COLUMNS,
@@ -56,7 +58,7 @@ export function AdminFaqsView({ children, onBulkArchive, onBulkDelete, ...props
56
58
  updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
57
59
  })),
58
60
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
59
- buildFilters: (state) => state.isActive ? `isActive==${state.isActive}` : undefined,
61
+ buildFilters: (state) => state.isActive ? sieveFilter("isActive", SIEVE_OP.EQ, state.isActive) : undefined,
60
62
  primaryAction: {
61
63
  label: "Add FAQ",
62
64
  onClick: ({ openCreatePanel }) => openCreatePanel(),
@@ -79,7 +81,7 @@ export function AdminFaqsView({ children, onBulkArchive, onBulkDelete, ...props
79
81
  ]
80
82
  : []),
81
83
  ],
82
- 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: [
84
+ 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: [
83
85
  { label: "All", value: "" },
84
86
  { label: "Published", value: "true" },
85
87
  { label: "Draft", value: "false" },
@@ -7,6 +7,12 @@ import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
8
  import { ERROR_MESSAGES } from "../../../errors/messages";
9
9
  import { PRODUCT_FEATURE_CATEGORY_OPTIONS, PRODUCT_FEATURE_DEFAULT_DISPLAY_ORDER, PRODUCT_FEATURE_ICON_COLOR_OPTIONS, PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS, PRODUCT_FEATURE_SCOPE_OPTIONS, } from "../../products/constants/product-features.constants";
10
+ const __P = {
11
+ p4: "p-4",
12
+ };
13
+ const __O = {
14
+ yAuto: "overflow-y-auto",
15
+ };
10
16
  const PILL_BASE_CLASS = "inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-medium cursor-pointer transition-colors";
11
17
  const PILL_CHECKED_CLASS = "bg-primary text-white border-primary";
12
18
  const PILL_UNCHECKED_CLASS = "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800";
@@ -142,7 +148,7 @@ export function AdminFeatureEditorView({ featureId, fixedScope, fixedStoreId, em
142
148
  }) })] }), !fixedScope && (_jsx(Select, { label: "Scope", value: scope, onChange: (e) => setScope(e.target.value), options: PRODUCT_FEATURE_SCOPE_OPTIONS })), scope === "store" && !fixedStoreId && (_jsx(Select, { label: "Store", value: storeId, onChange: (e) => setStoreId(e.target.value), options: storeOptions, required: true, helperText: "Store-scope features are visible only on this store's listings." })), _jsx(Toggle, { label: "Active", checked: isActive, onChange: setIsActive }), _jsxs(Div, { className: "flex gap-3 pt-2", children: [_jsx(Button, { type: "submit", isLoading: isSubmitting, disabled: isDisabled, children: isEdit ? "Save changes" : "Create feature" }), isEdit && (_jsx(Button, { type: "button", variant: "danger", isLoading: deleteMutation.isPending, onClick: () => setDeleteConfirmOpen(true), children: "Delete" }))] })] }) }, "feature-form"));
143
149
  const deleteModal = deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Feature", message: DELETE_CONFIRM_TEXT, onConfirm: () => { deleteMutation.mutate(); setDeleteConfirmOpen(false); }, onClose: () => setDeleteConfirmOpen(false), isDeleting: deleteMutation.isPending }));
144
150
  if (embedded) {
145
- return _jsxs(Div, { className: "overflow-y-auto p-4", children: [formSection, deleteModal] });
151
+ return _jsxs(Div, { className: `${__O.yAuto} ${__P.p4}`, children: [formSection, deleteModal] });
146
152
  }
147
153
  return (_jsxs(_Fragment, { children: [_jsx(StackedViewShell, { portal: "admin", ...rest, title: isEdit ? "Edit Feature" : "New Feature", sections: [formSection] }), deleteModal] }));
148
154
  }
@@ -5,6 +5,9 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
5
  import { Alert, Button, Div, Form, FormActions, Input, StackedViewShell, Text, Toggle, useToast, } from "../../../ui";
6
6
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
7
7
  import { apiClient } from "../../../http";
8
+ const __O = {
9
+ hidden: "overflow-hidden",
10
+ };
8
11
  // Platform feature keys (flat booleans with rollout % support)
9
12
  const PLATFORM_FLAGS = [
10
13
  { key: "blog", label: "Blog Posts", desc: "Publish articles for admins / sellers" },
@@ -38,7 +41,7 @@ const CATEGORY_TYPE_FLAGS = [
38
41
  ];
39
42
  function AccordionSection({ title, defaultOpen = true, children }) {
40
43
  const [open, setOpen] = React.useState(defaultOpen);
41
- return (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 bg-zinc-50 dark:bg-zinc-800/60 text-left", "aria-expanded": open, children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: title }), _jsx("svg", { className: `h-4 w-4 text-zinc-400 transition-transform ${open ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Div, { className: "divide-y divide-zinc-100 dark:divide-zinc-800", children: children }))] }));
44
+ return (_jsxs(Div, { className: `rounded-lg border border-zinc-200 dark:border-zinc-700 ${__O.hidden}`, children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 bg-zinc-50 dark:bg-zinc-800/60 text-left", "aria-expanded": open, children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest text-zinc-500 dark:text-zinc-400", children: title }), _jsx("svg", { className: `h-4 w-4 text-zinc-400 transition-transform ${open ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Div, { className: "divide-y divide-zinc-100 dark:divide-zinc-800", children: children }))] }));
42
45
  }
43
46
  function FlagRow({ label, desc, checked, onChange, rollout, onRolloutChange, showRollout }) {
44
47
  return (_jsxs(Div, { surface: "default", padding: "inline", className: "flex items-center justify-between gap-4", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Toggle, { checked: checked, onChange: onChange, label: label }), _jsx(Text, { className: "mt-0.5 ml-10 text-xs text-zinc-400 dark:text-zinc-400 truncate", children: desc })] }), showRollout && (_jsxs(Div, { className: "flex flex-col gap-1 w-28 shrink-0", children: [_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "Rollout %" }), _jsx(Input, { type: "number", min: 0, max: 100, value: rollout ?? 100, onChange: (e) => onRolloutChange?.(Math.min(100, Math.max(0, Number(e.target.value)))), disabled: !checked, className: "w-full" })] }))] }));
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { sortBy } from "@mohasinac/appkit";
3
4
  import React from "react";
4
5
  import { useRouter, useSearchParams, usePathname } from "next/navigation";
5
6
  import { ListingLayout, Row } from "../../../ui";
@@ -44,15 +45,15 @@ export function AdminFeaturesView({ children, ...props }) {
44
45
  searchPlaceholder: "Search features by label",
45
46
  emptyLabel: "No features found",
46
47
  filterKeys: [],
47
- defaultSort: "displayOrder",
48
+ defaultSort: sortBy("displayOrder", "ASC"),
48
49
  pageSize: PAGE_SIZE,
49
50
  queryKey: ["admin", "features", "listing", scopeFilter],
50
51
  endpoint: `${ADMIN_ENDPOINTS.PRODUCT_FEATURES}?scope=${scopeFilter}`,
51
52
  sortOptions: [
52
- { value: "displayOrder", label: "Display order" },
53
+ { value: sortBy("displayOrder", "ASC"), label: "Display order" },
53
54
  { value: "label", label: "Label A–Z" },
54
- { value: "-label", label: "Label Z–A" },
55
- { value: "-createdAt", label: "Newest" },
55
+ { value: sortBy("label", "DESC"), label: "Label Z–A" },
56
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
56
57
  ],
57
58
  mapRows: (response) => toRecordArray(response.items).map(mapFeatureRow),
58
59
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Button } from "@mohasinac/appkit/ui";
2
+ import { Button, Div } from "@mohasinac/appkit/ui";
3
3
  export function AdminFilterBar({ children, columns = 3, className = "", withCard = true, deferred = false, onApply, onReset, pendingCount = 0, labels = { apply: "Apply", reset: "Reset" }, themeConfig = { cardPadding: "p-4", flexEnd: "flex justify-end" }, }) {
4
4
  const gridCols = {
5
5
  1: "grid-cols-1",
@@ -7,7 +7,7 @@ export function AdminFilterBar({ children, columns = 3, className = "", withCard
7
7
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4",
8
8
  4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-4 2xl:grid-cols-4",
9
9
  };
10
- const innerContent = (_jsxs(_Fragment, { children: [_jsx("div", { className: `grid ${gridCols[columns]} gap-4`, "data-section": "adminfilterbar-div-249", children: children }), deferred && (_jsxs("div", { className: `${themeConfig.flexEnd} gap-2 mt-3`, "data-section": "adminfilterbar-div-250", children: [pendingCount > 0 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: onReset, children: labels.reset })), _jsx(Button, { variant: "primary", size: "sm", onClick: onApply, children: pendingCount > 0
10
+ const innerContent = (_jsxs(_Fragment, { children: [_jsx(Div, { className: `grid ${gridCols[columns]} gap-4`, children: children }), deferred && (_jsxs(Div, { className: `${themeConfig.flexEnd} gap-2 mt-3`, children: [pendingCount > 0 && (_jsx(Button, { variant: "ghost", size: "sm", onClick: onReset, children: labels.reset })), _jsx(Button, { variant: "primary", size: "sm", onClick: onApply, children: pendingCount > 0
11
11
  ? `${labels.applyCount || labels.apply} (${pendingCount})`
12
12
  : labels.apply })] }))] }));
13
13
  // If Card component is provided in config, use it; otherwise wrap in plain div
@@ -15,7 +15,7 @@ export function AdminFilterBar({ children, columns = 3, className = "", withCard
15
15
  return (_jsx(themeConfig.Card, { className: `${themeConfig.cardPadding} ${className}`, children: innerContent }));
16
16
  }
17
17
  if (!withCard)
18
- return _jsx("div", { className: className, "data-section": "adminfilterbar-div-251", children: innerContent });
18
+ return _jsx(Div, { className: className, children: innerContent });
19
19
  // Fallback: render as plain div if no Card provided but withCard=true
20
- return (_jsx("div", { className: `${themeConfig.cardPadding} ${className}`, "data-section": "adminfilterbar-div-252", children: innerContent }));
20
+ return (_jsx(Div, { className: `${themeConfig.cardPadding} ${className}`, children: innerContent }));
21
21
  }
@@ -1,43 +1,79 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  /**
4
4
  * AdminGroupedListingsView — admin moderation view for grouped product listings.
5
5
  * W1-29 — pairs with the new GET /api/admin/grouped-listings endpoint.
6
6
  */
7
- import React from "react";
7
+ import { sortBy } from "@mohasinac/appkit";
8
+ import React, { useState } from "react";
8
9
  import { ListingLayout } from "../../../ui";
10
+ import { Button, Row, SideDrawer, Stack, Text, useToast, } from "../../../ui";
9
11
  import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
10
12
  import { DataListingView } from "./DataListingView";
11
- const ADMIN_GROUPED_LISTINGS_CONFIG = {
12
- portal: "admin",
13
- title: "Grouped Listings",
14
- searchPlaceholder: "Search grouped listings by title or seller",
15
- emptyLabel: "No grouped listings",
16
- filterKeys: [],
17
- defaultSort: "-createdAt",
18
- queryKey: ["admin", "grouped-listings"],
19
- endpoint: "/api/admin/grouped-listings",
20
- sortOptions: [
21
- { value: "-createdAt", label: "Newest" },
22
- { value: "createdAt", label: "Oldest" },
23
- { value: "title", label: "Title A–Z" },
24
- ],
25
- mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
26
- id: toStringValue(item.id, `grouped-listing-${index}`),
27
- primary: toStringValue(item.title ?? item.name, "Untitled group"),
28
- secondary: [
29
- toStringValue(item.storeName ?? item.storeId, "Unknown store"),
30
- `${Array.isArray(item.productIds) ? item.productIds.length : 0} items`,
31
- ].join(" · "),
32
- status: toStringValue(item.isActive === false ? "inactive" : "active", "active"),
33
- updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
34
- })),
35
- getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
36
- buildFilters: () => "",
37
- };
13
+ import { ProductInlineSelect } from "../../seller/components/ProductInlineSelect";
14
+ import { apiClient } from "../../../http";
15
+ import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
16
+ function ReassignProductsDrawer({ state, onClose, onSaved, }) {
17
+ const [productIds, setProductIds] = useState(state.currentProductIds);
18
+ const [saving, setSaving] = useState(false);
19
+ const { showToast } = useToast();
20
+ const handleSave = async () => {
21
+ setSaving(true);
22
+ try {
23
+ await apiClient.patch(ADMIN_ENDPOINTS.GROUPED_LISTING_BY_ID(state.groupId), { productIds });
24
+ showToast("Products reassigned.", "success");
25
+ onSaved();
26
+ onClose();
27
+ }
28
+ catch {
29
+ showToast("Failed to save changes.", "error");
30
+ }
31
+ finally {
32
+ setSaving(false);
33
+ }
34
+ };
35
+ return (_jsxs(Stack, { gap: "md", padding: "md", children: [_jsxs(Text, { size: "sm", color: "muted", children: ["Select products to include in \u201C", state.groupTitle, "\u201D. Changes replace the current list."] }), _jsx(ProductInlineSelect, { scope: "admin", multiple: true, value: productIds, onChange: setProductIds, placeholder: "Search products to add\u2026" }), _jsxs(Row, { justify: "end", gap: "sm", children: [_jsx(Button, { variant: "outline", onClick: onClose, disabled: saving, children: "Cancel" }), _jsxs(Button, { variant: "primary", onClick: handleSave, disabled: saving, isLoading: saving, children: ["Save (", productIds.length, " product", productIds.length !== 1 ? "s" : "", ")"] })] })] }));
36
+ }
38
37
  export function AdminGroupedListingsView({ children, ...props }) {
38
+ const [reassign, setReassign] = useState(null);
39
+ const [refreshKey, setRefreshKey] = useState(0);
40
+ const config = React.useMemo(() => ({
41
+ portal: "admin",
42
+ title: "Grouped Listings",
43
+ searchPlaceholder: "Search grouped listings by title or seller",
44
+ emptyLabel: "No grouped listings",
45
+ filterKeys: [],
46
+ defaultSort: sortBy("createdAt", "DESC"),
47
+ queryKey: ["admin", "grouped-listings", refreshKey],
48
+ endpoint: ADMIN_ENDPOINTS.GROUPED_LISTINGS,
49
+ sortOptions: [
50
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
51
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
52
+ { value: "title", label: "Title A–Z" },
53
+ ],
54
+ mapRows: (response) => toRecordArray(response.items).map((item, index) => ({
55
+ id: toStringValue(item.id, `grouped-listing-${index}`),
56
+ primary: toStringValue(item.title ?? item.name, "Untitled group"),
57
+ secondary: [
58
+ toStringValue(item.storeName ?? item.storeId, "Unknown store"),
59
+ `${Array.isArray(item.productIds) ? item.productIds.length : 0} items`,
60
+ ].join(" · "),
61
+ status: toStringValue(item.isActive === false ? "inactive" : "active", "active"),
62
+ updatedAt: toRelativeDate(item.updatedAt ?? item.createdAt),
63
+ _raw: item,
64
+ })),
65
+ getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
66
+ buildFilters: () => "",
67
+ renderRowActions: (row) => (_jsx(Button, { size: "sm", variant: "outline", onClick: () => setReassign({
68
+ groupId: row.id,
69
+ groupTitle: row.primary,
70
+ currentProductIds: Array.isArray(row._raw?.productIds)
71
+ ? (row._raw?.productIds ?? []).map(String)
72
+ : [],
73
+ }), children: "Reassign products" })),
74
+ }), [refreshKey]);
39
75
  if (React.Children.count(children) > 0) {
40
76
  return (_jsx(ListingLayout, { portal: "admin", ...props, children: children }));
41
77
  }
42
- return _jsx(DataListingView, { config: ADMIN_GROUPED_LISTINGS_CONFIG });
78
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(SideDrawer, { isOpen: reassign !== null, onClose: () => setReassign(null), title: reassign ? `Reassign products — ${reassign.groupTitle}` : "Reassign products", children: reassign && (_jsx(ReassignProductsDrawer, { state: reassign, onClose: () => setReassign(null), onSaved: () => setRefreshKey((k) => k + 1) })) })] }));
43
79
  }
@@ -2,6 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Users, Package, Store, ShoppingBag, FileText, Settings, Shield, BarChart2, AlertTriangle, BookOpen, } from "lucide-react";
3
3
  import { Div, Heading, Text, Section, Alert } from "../../../ui";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
+ const CLS_WARN_PANEL = "rounded-2xl border border-amber-200 bg-warning-surface dark:border-amber-800 p-6";
6
+ const CLS_WARN_HEAD = "font-semibold text-amber-800 dark:text-amber-300 mb-1";
7
+ const CLS_WARN_BODY = "text-sm text-amber-700 dark:text-amber-400";
5
8
  const GUIDE_CARDS = [
6
9
  {
7
10
  Icon: Users,
@@ -75,5 +78,5 @@ export function AdminGuideHubView({ permissions = [], isFullAdmin = false }) {
75
78
  background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 60%,var(--appkit-color-secondary-400,#7c3aed) 100%)",
76
79
  }, children: [_jsxs(Div, { className: "flex items-center gap-3 mb-3", children: [_jsx(Div, { className: "flex-shrink-0 w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center", children: _jsx(BookOpen, { className: "w-5 h-5 text-white" }) }), _jsx(Text, { className: "text-sm font-semibold text-white/80 uppercase tracking-widest", children: "Admin & Employee Guide" })] }), _jsx(Heading, { level: 1, className: "text-2xl md:text-3xl font-bold text-white mb-2", children: "LetItRip Internal Guide" }), _jsx(Text, { className: "text-white/80 text-base", children: "Everything you need to operate and manage LetItRip \u2014 India's largest collectibles marketplace." })] }) }), _jsx(Alert, { variant: "info", compact: true, children: "These guides describe expected platform behaviour. Real access to each section is enforced independently by the permission system \u2014 this page is reference only." }), !hasAny && (_jsx(Alert, { variant: "info", title: "Limited access", children: "Your permission set doesn't include read access to any admin sections yet. Contact your admin to request the permissions you need." })), hasAny && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text)] mb-4", children: "Guides" }), _jsx(Div, { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: visibleCards.map(({ Icon, title, description, href }) => (_jsxs("a", { href: href, className: "group flex flex-col gap-3 rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] p-5 hover:border-[var(--appkit-color-primary)] hover:shadow-md transition-all", children: [_jsxs(Div, { className: "flex items-center gap-3", children: [_jsx(Div, { className: "flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center", style: {
77
80
  background: "linear-gradient(135deg,var(--appkit-color-primary-700,#4f46e5) 0%,var(--appkit-color-cobalt,#2563eb) 100%)",
78
- }, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: "rounded-2xl border border-amber-200 bg-warning-surface dark:border-amber-800 p-6", children: _jsxs(Div, { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "w-5 h-5 text-warning flex-shrink-0 mt-0.5" }), _jsxs(Div, { children: [_jsx(Text, { className: "font-semibold text-amber-800 dark:text-amber-300 mb-1", children: "Remember: with great access comes responsibility" }), _jsx(Text, { className: "text-sm text-amber-700 dark:text-amber-400", children: "Admin actions are logged. Never access user PII (email, phone) without a legitimate support reason. Never grant capabilities or permissions without documented approval. When in doubt, escalate to a senior admin." })] })] }) })] }));
81
+ }, children: _jsx(Icon, { className: "w-4 h-4 text-white" }) }), _jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)] group-hover:text-[var(--appkit-color-primary)] transition-colors", children: title })] }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] leading-relaxed", children: description }), _jsx(Text, { className: "text-xs font-medium text-[var(--appkit-color-primary)] mt-auto", children: "Read guide \u2192" })] }, title))) })] })), _jsx(Section, { className: CLS_WARN_PANEL, children: _jsxs(Div, { className: "flex items-start gap-3", children: [_jsx(AlertTriangle, { className: "w-5 h-5 text-warning flex-shrink-0 mt-0.5" }), _jsxs(Div, { children: [_jsx(Text, { className: CLS_WARN_HEAD, children: "Remember: with great access comes responsibility" }), _jsx(Text, { className: CLS_WARN_BODY, children: "Admin actions are logged. Never access user PII (email, phone) without a legitimate support reason. Never grant capabilities or permissions without documented approval. When in doubt, escalate to a senior admin." })] })] }) })] }));
79
82
  }
@@ -4,6 +4,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
4
4
  * AdminHistoryView — read-only admin insights for the top-level `history` collection.
5
5
  * One row per user with item count + last visit. Mirrors AdminWishlistsView.
6
6
  */
7
+ import { sortBy } from "@mohasinac/appkit";
7
8
  import React from "react";
8
9
  import { ListingLayout } from "../../../ui";
9
10
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -15,12 +16,12 @@ const ADMIN_HISTORY_CONFIG = {
15
16
  searchPlaceholder: "Search by user ID",
16
17
  emptyLabel: "No user history records found",
17
18
  filterKeys: [],
18
- defaultSort: "-updatedAt",
19
+ defaultSort: sortBy("updatedAt", "DESC"),
19
20
  queryKey: ["admin", "history", "listing"],
20
21
  endpoint: ADMIN_ENDPOINTS.ADMIN_HISTORY,
21
22
  sortOptions: [
22
- { value: "-updatedAt", label: "Recently active" },
23
- { value: "-itemCount", label: "Largest first" },
23
+ { value: sortBy("updatedAt", "DESC"), label: "Recently active" },
24
+ { value: sortBy("itemCount", "DESC"), label: "Largest first" },
24
25
  ],
25
26
  mapRows: (response) => toRecordArray(response.items).map((item, index) => {
26
27
  const itemCount = typeof item.itemCount === "number" ? item.itemCount : 0;
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  /**
4
4
  * AdminLiveView — admin browse of live-item listings (W1-29).
5
5
  */
6
+ import { sortBy } from "@mohasinac/appkit";
6
7
  import React from "react";
7
8
  import { ListingLayout } from "../../../ui";
8
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
@@ -14,12 +15,12 @@ const ADMIN_LIVE_CONFIG = {
14
15
  searchPlaceholder: "Search live items",
15
16
  emptyLabel: "No live item listings",
16
17
  filterKeys: [],
17
- defaultSort: "-createdAt",
18
+ defaultSort: sortBy("createdAt", "DESC"),
18
19
  queryKey: ["admin", "live-items", "listing"],
19
20
  endpoint: ADMIN_ENDPOINTS.PRODUCTS,
20
21
  sortOptions: [
21
- { value: "-createdAt", label: "Newest" },
22
- { value: "createdAt", label: "Oldest" },
22
+ { value: sortBy("createdAt", "DESC"), label: "Newest" },
23
+ { value: sortBy("createdAt", "ASC"), label: "Oldest" },
23
24
  { value: "title", label: "Title A–Z" },
24
25
  ],
25
26
  mapRows: (response) => toRecordArray(response.items).map((item, index) => {
@@ -4,6 +4,9 @@ import React from "react";
4
4
  import { Alert, Button, Div, Input, Select, StackedViewShell, Text, useToast, } from "../../../ui";
5
5
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
6
6
  import { MediaUploadField, MediaUploadList, useMediaCleanup, useMediaUpload, } from "../../media";
7
+ const __P = {
8
+ p4: "p-4",
9
+ };
7
10
  const PREFIX_OPTIONS = [
8
11
  { value: "", label: "All" },
9
12
  { value: "products/", label: "Products" },
@@ -58,7 +61,7 @@ function MediaBrowser({ onCopy }) {
58
61
  return files;
59
62
  return files.filter((f) => f.name.toLowerCase().includes(q));
60
63
  }, [files, search]);
61
- return (_jsxs(Div, { className: "space-y-3 rounded-xl border border-zinc-200 bg-white p-4 dark:border-slate-700 dark:bg-slate-900", children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Browse existing media" }), _jsxs(Div, { className: "flex flex-wrap items-center gap-2", children: [_jsx(Select, { value: prefix, onChange: (e) => setPrefix(e.target.value), options: PREFIX_OPTIONS, "aria-label": "Prefix filter", className: "min-w-[140px]" }), _jsx(Input, { type: "text", placeholder: "Search filename\u2026", value: search, onChange: (e) => setSearch(e.target.value), className: "flex-1 min-w-[160px]" })] }), error && (_jsx(Alert, { variant: "error", title: "Load failed", children: error })), _jsxs(Div, { className: "grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6", children: [filtered.map((f) => {
64
+ return (_jsxs(Div, { className: `space-y-3 rounded-xl border border-zinc-200 bg-white ${__P.p4} dark:border-slate-700 dark:bg-slate-900`, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Browse existing media" }), _jsxs(Div, { className: "flex flex-wrap items-center gap-2", children: [_jsx(Select, { value: prefix, onChange: (e) => setPrefix(e.target.value), options: PREFIX_OPTIONS, "aria-label": "Prefix filter", className: "min-w-[140px]" }), _jsx(Input, { type: "text", placeholder: "Search filename\u2026", value: search, onChange: (e) => setSearch(e.target.value), className: "flex-1 min-w-[160px]" })] }), error && (_jsx(Alert, { variant: "error", title: "Load failed", children: error })), _jsxs(Div, { className: "grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6", children: [filtered.map((f) => {
62
65
  const isImage = (f.contentType ?? "").startsWith("image/");
63
66
  return (_jsxs(Div, { className: "group rounded-lg border border-zinc-200 dark:border-slate-700 overflow-hidden bg-zinc-50 dark:bg-slate-800", children: [_jsx(Div, { className: "aspect-square flex items-center justify-center bg-zinc-100 dark:bg-slate-700 text-xs text-zinc-500 dark:text-zinc-400", children: isImage ? (
64
67
  // eslint-disable-next-line @next/next/no-img-element
@@ -2,13 +2,16 @@
2
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, useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { Alert, Button, ConfirmDeleteModal, RowActionMenu, StackedViewShell, Text, Toggle, useToast } from "../../../ui";
5
+ import { Alert, Button, ConfirmDeleteModal, Div, RowActionMenu, Span, StackedViewShell, Text, Toggle, useToast } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
8
  import { AdminNavEditorView } from "./AdminNavEditorView";
9
9
  import { ROW_ACTION_META, ROW_ACTION_ID } from "../../../features/products/constants/action-defs";
10
+ const __O = {
11
+ hidden: "overflow-hidden",
12
+ };
10
13
  function NavItemRow({ item, idx, total, reorderPending, onMoveUp, onMoveDown, onVisibilityChange, onEdit, onDelete, }) {
11
- return (_jsxs("div", { className: "flex items-center gap-3 px-4 py-3 bg-white dark:bg-zinc-900", children: [_jsxs("div", { className: "flex flex-col gap-0.5 shrink-0", children: [_jsx("button", { type: "button", onClick: () => onMoveUp(idx), disabled: idx === 0 || reorderPending, className: "text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 disabled:opacity-30 leading-none text-xs", "aria-label": "Move up", children: "\u25B2" }), _jsx("button", { type: "button", onClick: () => onMoveDown(idx), disabled: idx >= total - 1 || reorderPending, className: "text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 disabled:opacity-30 leading-none text-xs", "aria-label": "Move down", children: "\u25BC" })] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-100 truncate", children: [item.parentId ? _jsx("span", { className: "text-zinc-400 mr-1", children: "\u21B3" }) : null, item.label] }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 truncate", children: item.href })] }), _jsx(Toggle, { checked: item.isVisible ?? true, onChange: (val) => onVisibilityChange(item.id, val), label: "" }), _jsx(RowActionMenu, { actions: [
14
+ return (_jsxs(Div, { surface: "default", className: "flex items-center gap-3 px-4 py-3", children: [_jsxs(Div, { className: "flex flex-col gap-0.5 shrink-0", children: [_jsx(Button, { variant: "ghost", type: "button", onClick: () => onMoveUp(idx), disabled: idx === 0 || reorderPending, className: "text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 disabled:opacity-30 leading-none text-xs p-0 min-h-0 h-auto rounded-none", "aria-label": "Move up", children: "\u25B2" }), _jsx(Button, { variant: "ghost", type: "button", onClick: () => onMoveDown(idx), disabled: idx >= total - 1 || reorderPending, className: "text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 disabled:opacity-30 leading-none text-xs p-0 min-h-0 h-auto rounded-none", "aria-label": "Move down", children: "\u25BC" })] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Text, { className: "text-sm font-medium text-zinc-800 dark:text-zinc-100 truncate", children: [item.parentId ? _jsx(Span, { className: "text-zinc-400 mr-1", children: "\u21B3" }) : null, item.label] }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 truncate", children: item.href })] }), _jsx(Toggle, { checked: item.isVisible ?? true, onChange: (val) => onVisibilityChange(item.id, val), label: "" }), _jsx(RowActionMenu, { actions: [
12
15
  { label: ROW_ACTION_META[ROW_ACTION_ID.EDIT].label, onClick: () => onEdit(item) },
13
16
  { label: ROW_ACTION_META[ROW_ACTION_ID.DELETE].label, destructive: true, onClick: () => onDelete(item) },
14
17
  ] })] }));
@@ -78,11 +81,11 @@ export function AdminNavigationView({ labels = {}, ...rest }) {
78
81
  return (_jsxs(_Fragment, { children: [_jsx(StackedViewShell, { portal: "admin", ...rest, title: labels.title ?? "Navigation", sections: [
79
82
  isLoading ? (_jsx(Alert, { variant: "info", title: "Loading", children: "Fetching nav items\u2026" }, "loading")) : null,
80
83
  error ? (_jsx(Alert, { variant: "error", title: "Load failed", children: error instanceof Error ? error.message : "Unknown error" }, "error")) : null,
81
- _jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [sorted.length, " nav item", sorted.length !== 1 ? "s" : ""] }), _jsx(Button, { onClick: () => {
84
+ _jsxs(Div, { className: "flex items-center justify-between mb-4", children: [_jsxs(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [sorted.length, " nav item", sorted.length !== 1 ? "s" : ""] }), _jsx(Button, { onClick: () => {
82
85
  setEditing(null);
83
86
  setDrawerOpen(true);
84
87
  }, children: "+ New item" })] }, "header"),
85
88
  sorted.length === 0 && !isLoading ? (_jsx(Text, { className: "text-sm text-zinc-400 dark:text-zinc-400 py-8 text-center", children: "No nav items yet. Click \"New item\" to add one." }, "empty")) : null,
86
- _jsx("div", { className: "divide-y divide-zinc-200 dark:divide-zinc-700 rounded-lg border border-zinc-200 dark:border-zinc-700 overflow-hidden", children: sorted.map((item, idx) => (_jsx(NavItemRow, { item: item, idx: idx, total: sorted.length, reorderPending: reorderMutation.isPending, onMoveUp: handleMoveUp, onMoveDown: handleMoveDown, onVisibilityChange: (id, isVisible) => visibilityMutation.mutate({ id, isVisible }), onEdit: (i) => { setEditing(i); setDrawerOpen(true); }, onDelete: setDeleteTarget }, item.id))) }, "list"),
89
+ _jsx(Div, { className: `divide-y divide-zinc-200 dark:divide-zinc-700 rounded-lg border border-zinc-200 dark:border-zinc-700 ${__O.hidden}`, children: sorted.map((item, idx) => (_jsx(NavItemRow, { item: item, idx: idx, total: sorted.length, reorderPending: reorderMutation.isPending, onMoveUp: handleMoveUp, onMoveDown: handleMoveDown, onVisibilityChange: (id, isVisible) => visibilityMutation.mutate({ id, isVisible }), onEdit: (i) => { setEditing(i); setDrawerOpen(true); }, onDelete: setDeleteTarget }, item.id))) }, "list"),
87
90
  ] }), _jsx(AdminNavEditorView, { open: drawerOpen, onClose: () => setDrawerOpen(false), onSaved: () => queryClient.invalidateQueries({ queryKey: ["admin", "navigation"] }), item: editing, parentOptions: parentOptions }), _jsx(ConfirmDeleteModal, { isOpen: Boolean(deleteTarget), onClose: () => setDeleteTarget(null), onConfirm: () => deleteMutation.mutate(deleteTarget.id), isDeleting: deleteMutation.isPending, title: "Delete nav item", message: `Remove "${deleteTarget?.label}" from navigation? This cannot be undone.` })] }));
88
91
  }