@mohasinac/appkit 3.4.8 → 3.5.1

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 (605) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +1 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +1 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +1 -1
  4. package/dist/_internal/client/features/filters/filter-load-options.js +10 -9
  5. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  6. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +11 -4
  7. package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
  8. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +10 -3
  9. package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +2 -2
  10. package/dist/_internal/client/scaffolds/DashboardScaffold.js +3 -1
  11. package/dist/_internal/server/features/checkout/actions.d.ts +16 -0
  12. package/dist/_internal/server/features/checkout/actions.js +149 -35
  13. package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +31 -0
  14. package/dist/_internal/server/features/checkout/bundle-expansion.js +41 -0
  15. package/dist/_internal/server/features/lottery/actions.js +14 -4
  16. package/dist/_internal/server/features/maintenance/analyze.js +4 -2
  17. package/dist/_internal/server/features/orders/actions.js +9 -0
  18. package/dist/_internal/server/features/orders/adapters.js +19 -0
  19. package/dist/_internal/server/features/seo/robots.js +1 -1
  20. package/dist/_internal/server/functions/firestore.d.ts +47 -1
  21. package/dist/_internal/server/functions/firestore.js +56 -1
  22. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  23. package/dist/_internal/server/functions/scheduled.js +9 -1
  24. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.d.ts +10 -0
  25. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.js +49 -0
  26. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +32 -0
  27. package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +26 -0
  28. package/dist/_internal/server/jobs/core/hardBanCascade.js +181 -0
  29. package/dist/_internal/server/jobs/core/index.d.ts +4 -1
  30. package/dist/_internal/server/jobs/core/index.js +4 -1
  31. package/dist/_internal/server/jobs/core/jobRunners.d.ts +28 -0
  32. package/dist/_internal/server/jobs/core/jobRunners.js +37 -0
  33. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +15 -0
  34. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +38 -0
  35. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +22 -0
  36. package/dist/_internal/server/jobs/core/onJobCreated.js +59 -0
  37. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -1
  38. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -2
  39. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.d.ts +2 -0
  40. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.js +2 -0
  41. package/dist/_internal/server/jobs/handlers/index.d.ts +6 -0
  42. package/dist/_internal/server/jobs/handlers/index.js +8 -0
  43. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.d.ts +12 -0
  44. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.js +20 -0
  45. package/dist/_internal/server/jobs/handlers/onJobCreated.d.ts +3 -0
  46. package/dist/_internal/server/jobs/handlers/onJobCreated.js +9 -0
  47. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +25 -0
  48. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +71 -0
  49. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.d.ts +14 -0
  50. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.js +23 -0
  51. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +17 -0
  52. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +26 -0
  53. package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +3 -1
  54. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  55. package/dist/_internal/shared/actions/action-registry.js +136 -0
  56. package/dist/_internal/shared/features/blog/schema.d.ts +8 -8
  57. package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
  58. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
  59. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  60. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  61. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  62. package/dist/_internal/shared/features/reviews/schema.d.ts +4 -4
  63. package/dist/client/api/useFeatureFlags.d.ts +22 -0
  64. package/dist/client/api/useFeatureFlags.js +27 -0
  65. package/dist/client/observability/reportClientError.js +3 -2
  66. package/dist/client.d.ts +4 -2
  67. package/dist/client.js +2 -1
  68. package/dist/configs/next.js +1 -0
  69. package/dist/constants/api-endpoints.d.ts +279 -3
  70. package/dist/constants/api-endpoints.js +130 -2
  71. package/dist/core/hooks/useSyncManager.js +5 -4
  72. package/dist/errors/conflict-error.d.ts +4 -0
  73. package/dist/errors/conflict-error.js +6 -0
  74. package/dist/errors/index.d.ts +1 -0
  75. package/dist/errors/index.js +1 -0
  76. package/dist/features/about/components/FeesView.js +2 -2
  77. package/dist/features/about/components/HelpPageView.js +2 -2
  78. package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
  79. package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
  80. package/dist/features/about/components/HowEmiWorksView.js +2 -2
  81. package/dist/features/about/components/HowOffersWorkView.js +3 -3
  82. package/dist/features/about/components/HowOrdersWorkView.js +3 -3
  83. package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
  84. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
  85. package/dist/features/about/components/HowReviewsWorkView.js +2 -2
  86. package/dist/features/about/components/PublicProfileView.d.ts +8 -1
  87. package/dist/features/about/components/PublicProfileView.js +11 -9
  88. package/dist/features/about/components/SecurityPrivacyView.js +2 -2
  89. package/dist/features/about/components/UnauthorizedView.js +2 -2
  90. package/dist/features/account/components/AddressBook.js +1 -1
  91. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  92. package/dist/features/account/components/NotificationBell.js +5 -5
  93. package/dist/features/account/components/NotificationPreferencesPanel.js +5 -2
  94. package/dist/features/account/components/UserOffersPanel.js +5 -4
  95. package/dist/features/account/components/UserSidebar.js +2 -2
  96. package/dist/features/account/components/UserSupportView.js +3 -3
  97. package/dist/features/account/schemas/index.d.ts +12 -12
  98. package/dist/features/addresses/schemas/index.d.ts +6 -6
  99. package/dist/features/admin/components/AdminAdEditorView.js +3 -3
  100. package/dist/features/admin/components/AdminAddressEditorView.js +3 -3
  101. package/dist/features/admin/components/AdminAdsView.js +3 -3
  102. package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
  103. package/dist/features/admin/components/AdminBlogView.js +12 -15
  104. package/dist/features/admin/components/AdminBrandEditorView.js +1 -1
  105. package/dist/features/admin/components/AdminBrandsView.js +12 -13
  106. package/dist/features/admin/components/AdminBundleEditorView.js +5 -4
  107. package/dist/features/admin/components/AdminBundlesView.js +32 -23
  108. package/dist/features/admin/components/AdminCarouselEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminCarouselView.js +2 -2
  110. package/dist/features/admin/components/AdminCatalogGuideView.js +1 -1
  111. package/dist/features/admin/components/AdminCategoriesView.js +12 -13
  112. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  113. package/dist/features/admin/components/AdminContactEditorView.js +2 -2
  114. package/dist/features/admin/components/AdminCouponEditorView.d.ts +10 -1
  115. package/dist/features/admin/components/AdminCouponEditorView.js +7 -2
  116. package/dist/features/admin/components/AdminCouponsView.js +32 -27
  117. package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
  118. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  119. package/dist/features/admin/components/AdminFaqsView.js +20 -20
  120. package/dist/features/admin/components/AdminFeatureEditorView.js +5 -5
  121. package/dist/features/admin/components/AdminFeaturesView.js +9 -10
  122. package/dist/features/admin/components/AdminFilterBar.js +1 -1
  123. package/dist/features/admin/components/AdminFulfillmentView.js +4 -4
  124. package/dist/features/admin/components/AdminGuideHubView.js +2 -2
  125. package/dist/features/admin/components/AdminMediaView.js +3 -2
  126. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  127. package/dist/features/admin/components/AdminOrderEditorView.js +3 -3
  128. package/dist/features/admin/components/AdminOrdersView.js +21 -30
  129. package/dist/features/admin/components/AdminPageHeader.js +3 -3
  130. package/dist/features/admin/components/AdminPayoutsView.js +8 -8
  131. package/dist/features/admin/components/AdminPrizeDrawsView.js +8 -9
  132. package/dist/features/admin/components/AdminProductEditorView.d.ts +9 -1
  133. package/dist/features/admin/components/AdminProductEditorView.js +7 -4
  134. package/dist/features/admin/components/AdminProductsView.js +30 -41
  135. package/dist/features/admin/components/AdminReviewsView.js +14 -17
  136. package/dist/features/admin/components/AdminScammerEditorView.js +5 -5
  137. package/dist/features/admin/components/AdminSectionsView.js +3 -3
  138. package/dist/features/admin/components/AdminSessionsView.js +8 -10
  139. package/dist/features/admin/components/AdminSidebar.js +2 -2
  140. package/dist/features/admin/components/AdminSiteSettingsView.js +10 -3
  141. package/dist/features/admin/components/AdminStoreEditorView.js +4 -5
  142. package/dist/features/admin/components/AdminStoresView.js +18 -13
  143. package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -7
  144. package/dist/features/admin/components/AdminTeamView.js +9 -5
  145. package/dist/features/admin/components/AdminUsersView.js +19 -15
  146. package/dist/features/admin/components/AdminViewCards.js +5 -5
  147. package/dist/features/admin/components/DashboardStats.js +1 -1
  148. package/dist/features/admin/components/DataListingView.js +2 -2
  149. package/dist/features/admin/components/DataTable.js +2 -2
  150. package/dist/features/admin/components/DrawerFormFooter.js +1 -1
  151. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +2 -2
  152. package/dist/features/admin/components/analytics/AdminStatCard.js +1 -1
  153. package/dist/features/admin/hooks/useAdminListing.d.ts +3 -2
  154. package/dist/features/admin/hooks/useAdminListing.js +8 -2
  155. package/dist/features/admin/permission-map.js +2 -0
  156. package/dist/features/admin/schemas/firestore.d.ts +7 -0
  157. package/dist/features/admin/schemas/firestore.js +4 -0
  158. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  159. package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
  160. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -3
  161. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +4 -4
  162. package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
  163. package/dist/features/auctions/schemas/index.d.ts +16 -16
  164. package/dist/features/auth/permissions/constants.d.ts +1 -1
  165. package/dist/features/auth/permissions/constants.js +2 -0
  166. package/dist/features/auth/schemas/index.d.ts +6 -6
  167. package/dist/features/before-after/schemas/index.d.ts +3 -3
  168. package/dist/features/blog/actions/blog-actions.d.ts +32 -32
  169. package/dist/features/blog/components/BlogFeaturedCard.js +2 -2
  170. package/dist/features/blog/components/BlogIndexListing.js +2 -2
  171. package/dist/features/blog/components/BlogListView.js +4 -4
  172. package/dist/features/blog/components/BlogPostView.js +4 -4
  173. package/dist/features/blog/schemas/index.d.ts +77 -77
  174. package/dist/features/cart/components/CartDrawer.js +2 -2
  175. package/dist/features/catalogue/actions/approve-catalogue-listing.d.ts +12 -0
  176. package/dist/features/catalogue/actions/approve-catalogue-listing.js +50 -0
  177. package/dist/features/catalogue/actions/list-from-catalogue.d.ts +17 -0
  178. package/dist/features/catalogue/actions/list-from-catalogue.js +50 -0
  179. package/dist/features/catalogue/actions/submit-for-approval.d.ts +8 -0
  180. package/dist/features/catalogue/actions/submit-for-approval.js +30 -0
  181. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.d.ts +2 -0
  182. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +53 -0
  183. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +7 -0
  184. package/dist/features/catalogue/components/CatalogueItemEditorView.js +79 -0
  185. package/dist/features/catalogue/components/PublicCatalogueView.d.ts +5 -0
  186. package/dist/features/catalogue/components/PublicCatalogueView.js +22 -0
  187. package/dist/features/catalogue/components/UserCatalogueView.d.ts +12 -0
  188. package/dist/features/catalogue/components/UserCatalogueView.js +51 -0
  189. package/dist/features/catalogue/index.d.ts +12 -0
  190. package/dist/features/catalogue/index.js +9 -0
  191. package/dist/features/catalogue/repository/catalogue.repository.d.ts +39 -0
  192. package/dist/features/catalogue/repository/catalogue.repository.js +68 -0
  193. package/dist/features/catalogue/schemas/firestore.d.ts +47 -0
  194. package/dist/features/catalogue/schemas/firestore.js +22 -0
  195. package/dist/features/catalogue/schemas/index.d.ts +2 -0
  196. package/dist/features/catalogue/schemas/index.js +2 -0
  197. package/dist/features/catalogue/schemas/validation.d.ts +71 -0
  198. package/dist/features/catalogue/schemas/validation.js +25 -0
  199. package/dist/features/catalogue/utils/freshness.d.ts +10 -0
  200. package/dist/features/catalogue/utils/freshness.js +15 -0
  201. package/dist/features/catalogue/utils/product-from-item.d.ts +15 -0
  202. package/dist/features/catalogue/utils/product-from-item.js +34 -0
  203. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  204. package/dist/features/categories/components/BrandDetailTabs.js +2 -2
  205. package/dist/features/categories/components/BundleCollage.js +2 -2
  206. package/dist/features/categories/components/BundleItemsPicker.js +3 -2
  207. package/dist/features/categories/components/CategoriesIndexListing.js +8 -6
  208. package/dist/features/categories/components/CategoryBundlesListing.js +10 -4
  209. package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
  210. package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
  211. package/dist/features/categories/components/CategoryGrid.js +3 -3
  212. package/dist/features/categories/components/CategoryProductsListing.js +1 -1
  213. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  214. package/dist/features/categories/components/CategoryStoresListing.js +1 -1
  215. package/dist/features/categories/components/CategoryTableColumns.js +1 -1
  216. package/dist/features/categories/components/CategoryTree.js +2 -2
  217. package/dist/features/categories/components/ConcernCard.js +1 -1
  218. package/dist/features/categories/hooks/useCategories.js +1 -1
  219. package/dist/features/categories/schemas/index.d.ts +32 -32
  220. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  221. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  222. package/dist/features/collections/schemas/index.d.ts +2 -2
  223. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  224. package/dist/features/consultation/schemas/index.d.ts +10 -10
  225. package/dist/features/contact/components/ContactForm.js +4 -4
  226. package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
  227. package/dist/features/contact/components/ContactPageView.js +2 -1
  228. package/dist/features/copilot/components/AdminCopilotView.js +5 -4
  229. package/dist/features/corporate/schemas/index.d.ts +2 -2
  230. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +3 -3
  231. package/dist/features/events/components/AdminEventEditorView.js +4 -4
  232. package/dist/features/events/components/AdminEventEntriesView.js +2 -2
  233. package/dist/features/events/components/AdminEventsView.js +8 -8
  234. package/dist/features/events/components/EventBanner.js +1 -1
  235. package/dist/features/events/components/EventCard.js +3 -3
  236. package/dist/features/events/components/EventLeaderboard.js +1 -1
  237. package/dist/features/events/components/EventOfferCard.js +1 -1
  238. package/dist/features/events/components/EventPollWidget.js +6 -5
  239. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  240. package/dist/features/events/components/EventRaffleWinnerView.js +5 -5
  241. package/dist/features/events/components/EventRafflesSection.js +1 -1
  242. package/dist/features/events/components/EventSaleBanner.js +1 -1
  243. package/dist/features/events/components/EventsIndexListing.js +4 -2
  244. package/dist/features/events/components/EventsListView.js +2 -2
  245. package/dist/features/events/components/SpinWheelView.js +11 -5
  246. package/dist/features/events/schemas/index.d.ts +100 -100
  247. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  248. package/dist/features/faq/components/ContactCTA.js +3 -3
  249. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  250. package/dist/features/faq/components/FAQHelpfulButtons.js +3 -3
  251. package/dist/features/faq/schemas/index.d.ts +12 -12
  252. package/dist/features/filters/AsyncFacetSection.js +4 -4
  253. package/dist/features/filters/FilterFacetSection.js +8 -8
  254. package/dist/features/filters/RangeFilter.js +2 -2
  255. package/dist/features/filters/SwitchFilter.js +1 -1
  256. package/dist/features/forms/Checkbox.js +2 -8
  257. package/dist/features/forms/Input.js +2 -1
  258. package/dist/features/forms/Radio.js +3 -3
  259. package/dist/features/forms/Select.d.ts +1 -1
  260. package/dist/features/forms/Select.js +3 -2
  261. package/dist/features/forms/Slider.js +5 -11
  262. package/dist/features/forms/Textarea.js +2 -1
  263. package/dist/features/grouped/schemas/index.d.ts +6 -6
  264. package/dist/features/homepage/actions/homepage-section-actions.d.ts +4 -4
  265. package/dist/features/homepage/components/AdvertisementBanner.js +4 -4
  266. package/dist/features/homepage/components/AnnouncementBar.js +3 -3
  267. package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
  268. package/dist/features/homepage/components/BrandsSection.js +9 -9
  269. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  270. package/dist/features/homepage/components/CharacterHotspot.js +4 -4
  271. package/dist/features/homepage/components/CharacterHotspotForm.js +15 -13
  272. package/dist/features/homepage/components/CollectionCardsSection.js +1 -1
  273. package/dist/features/homepage/components/CustomCardsSection.js +6 -6
  274. package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
  275. package/dist/features/homepage/components/FAQSection.js +2 -2
  276. package/dist/features/homepage/components/FeaturedBundlesSection.js +3 -3
  277. package/dist/features/homepage/components/FeaturedResultsSection.js +2 -2
  278. package/dist/features/homepage/components/GoogleReviewsSection.js +6 -6
  279. package/dist/features/homepage/components/HeroBanner.js +1 -1
  280. package/dist/features/homepage/components/HeroCarousel.js +5 -4
  281. package/dist/features/homepage/components/HeroSection.js +1 -7
  282. package/dist/features/homepage/components/HomepageSkeleton.js +1 -1
  283. package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
  284. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  285. package/dist/features/homepage/components/NewsletterBanner.js +2 -2
  286. package/dist/features/homepage/components/NewsletterSection.js +1 -1
  287. package/dist/features/homepage/components/PromoGrid.js +1 -1
  288. package/dist/features/homepage/components/SectionCarousel.js +6 -6
  289. package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
  290. package/dist/features/homepage/components/ShopByCategorySection.js +10 -10
  291. package/dist/features/homepage/components/SiteFeaturesSection.js +2 -2
  292. package/dist/features/homepage/components/SocialFeedSection.js +5 -5
  293. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  294. package/dist/features/homepage/components/StatsCounterSection.js +1 -1
  295. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  296. package/dist/features/homepage/components/TrustBadges.js +1 -1
  297. package/dist/features/homepage/components/TrustFeaturesSection.js +2 -2
  298. package/dist/features/homepage/components/TrustIndicatorsSection.js +2 -2
  299. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  300. package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
  301. package/dist/features/homepage/hooks/useActiveAd.js +2 -1
  302. package/dist/features/homepage/schemas/firestore.d.ts +10 -0
  303. package/dist/features/homepage/schemas/index.d.ts +116 -116
  304. package/dist/features/jobs/actions/enqueue-job.d.ts +24 -0
  305. package/dist/features/jobs/actions/enqueue-job.js +44 -0
  306. package/dist/features/jobs/repository/jobs.repository.d.ts +21 -0
  307. package/dist/features/jobs/repository/jobs.repository.js +48 -0
  308. package/dist/features/jobs/schemas/firestore.d.ts +54 -0
  309. package/dist/features/jobs/schemas/firestore.js +24 -0
  310. package/dist/features/layout/AppLayoutShell.js +17 -11
  311. package/dist/features/layout/AutoBreadcrumbs.js +1 -1
  312. package/dist/features/layout/BackToTop.js +2 -2
  313. package/dist/features/layout/BottomActions.js +7 -7
  314. package/dist/features/layout/BottomNavItem.js +2 -2
  315. package/dist/features/layout/BottomNavLayout.js +13 -4
  316. package/dist/features/layout/BottomNavbar.d.ts +9 -1
  317. package/dist/features/layout/BottomNavbar.js +12 -5
  318. package/dist/features/layout/BottomSheet.js +1 -1
  319. package/dist/features/layout/Breadcrumbs.js +1 -1
  320. package/dist/features/layout/FooterLayout.js +2 -2
  321. package/dist/features/layout/NavItem.js +3 -3
  322. package/dist/features/layout/NavbarLayout.js +6 -6
  323. package/dist/features/layout/SidebarLayout.d.ts +3 -0
  324. package/dist/features/layout/SidebarLayout.js +3 -3
  325. package/dist/features/layout/TitleBarLayout.js +4 -4
  326. package/dist/features/live/components/LiveItemFilters.js +2 -2
  327. package/dist/features/live/components/LiveItemsIndexListing.js +3 -3
  328. package/dist/features/lottery/types/index.d.ts +3 -1
  329. package/dist/features/lottery/types/index.js +16 -3
  330. package/dist/features/loyalty/components/CoinsDisplay.js +2 -2
  331. package/dist/features/media/MediaImage.d.ts +6 -1
  332. package/dist/features/media/MediaImage.js +10 -4
  333. package/dist/features/media/MediaLightbox.js +1 -1
  334. package/dist/features/media/MediaPickerModal.js +4 -3
  335. package/dist/features/media/MediaVideo.js +1 -1
  336. package/dist/features/media/modals/ImageCropModal.js +1 -1
  337. package/dist/features/media/modals/ImageEditor.js +1 -1
  338. package/dist/features/media/repository/media-assets.repository.d.ts +9 -0
  339. package/dist/features/media/types/index.d.ts +4 -4
  340. package/dist/features/media/upload/MediaUploadField.js +3 -3
  341. package/dist/features/media/upload/MediaUploadList.js +1 -1
  342. package/dist/features/messages/hooks/useConversation.js +4 -3
  343. package/dist/features/messages/hooks/useConversations.js +2 -1
  344. package/dist/features/messages/schemas/index.d.ts +6 -6
  345. package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
  346. package/dist/features/orders/components/OrderPaymentSummary.d.ts +16 -0
  347. package/dist/features/orders/components/OrderPaymentSummary.js +32 -0
  348. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  349. package/dist/features/orders/components/OrdersList.d.ts +7 -2
  350. package/dist/features/orders/components/OrdersList.js +5 -5
  351. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  352. package/dist/features/orders/components/RefundRequestView.js +1 -1
  353. package/dist/features/orders/components/index.d.ts +2 -0
  354. package/dist/features/orders/components/index.js +1 -0
  355. package/dist/features/orders/repository/orders.repository.d.ts +8 -0
  356. package/dist/features/orders/repository/orders.repository.js +24 -0
  357. package/dist/features/orders/schemas/firestore.d.ts +59 -0
  358. package/dist/features/orders/schemas/firestore.js +5 -0
  359. package/dist/features/orders/schemas/index.d.ts +91 -40
  360. package/dist/features/orders/schemas/index.js +10 -0
  361. package/dist/features/orders/types/index.d.ts +15 -0
  362. package/dist/features/payments/schemas/index.d.ts +12 -12
  363. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -5
  364. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  365. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  366. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +7 -7
  367. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -3
  368. package/dist/features/pre-orders/schemas/index.d.ts +12 -12
  369. package/dist/features/products/columns/productTableColumns.js +2 -2
  370. package/dist/features/products/components/AuctionsIndexListing.js +3 -3
  371. package/dist/features/products/components/CompareOverlay.js +15 -10
  372. package/dist/features/products/components/CustomFieldsEditor.js +2 -2
  373. package/dist/features/products/components/CustomSectionsEditor.js +3 -3
  374. package/dist/features/products/components/FeatureBadge.js +2 -2
  375. package/dist/features/products/components/GroupSettingsPanel.js +5 -4
  376. package/dist/features/products/components/MakeOfferButton.js +4 -4
  377. package/dist/features/products/components/MarketplaceBundleCard.js +3 -2
  378. package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
  379. package/dist/features/products/components/PrizeDrawCollage.js +6 -6
  380. package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -5
  381. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  382. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -4
  383. package/dist/features/products/components/PrizeDrawsIndexListing.js +11 -4
  384. package/dist/features/products/components/PrizeDrawsSection.js +1 -1
  385. package/dist/features/products/components/PrizeRevealModal.js +9 -4
  386. package/dist/features/products/components/ProductDetailActions.js +2 -1
  387. package/dist/features/products/components/ProductDetailPageView.js +16 -16
  388. package/dist/features/products/components/ProductFeaturesSelector.js +5 -5
  389. package/dist/features/products/components/ProductForm.js +1 -1
  390. package/dist/features/products/components/ProductGalleryClient.js +5 -3
  391. package/dist/features/products/components/ProductGrid.js +11 -11
  392. package/dist/features/products/components/ProductTabs.js +2 -2
  393. package/dist/features/products/components/ProductTabsShell.js +2 -1
  394. package/dist/features/products/components/ProductsIndexListing.js +6 -1
  395. package/dist/features/products/components/ShareButton.js +2 -1
  396. package/dist/features/products/components/ShowGroupSection.js +9 -5
  397. package/dist/features/products/components/SublistingCarouselSection.js +8 -4
  398. package/dist/features/products/constants/action-defs.d.ts +10 -2
  399. package/dist/features/products/constants/action-defs.js +20 -2
  400. package/dist/features/products/schemas/firestore.d.ts +5 -0
  401. package/dist/features/products/schemas/index.d.ts +40 -40
  402. package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
  403. package/dist/features/promotions/components/CouponCard.js +13 -7
  404. package/dist/features/promotions/components/CouponsIndexListing.js +4 -6
  405. package/dist/features/promotions/components/PromotionsView.js +2 -2
  406. package/dist/features/promotions/schemas/index.d.ts +26 -26
  407. package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
  408. package/dist/features/reviews/components/ReviewDetailShell.js +11 -11
  409. package/dist/features/reviews/components/ReviewModal.js +1 -1
  410. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  411. package/dist/features/reviews/components/ReviewsList.js +2 -2
  412. package/dist/features/reviews/schemas/index.d.ts +22 -22
  413. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  414. package/dist/features/scams/components/ScamProfileView.js +3 -3
  415. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  416. package/dist/features/scams/schemas/index.d.ts +20 -20
  417. package/dist/features/search/components/Search.js +9 -9
  418. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  419. package/dist/features/search/components/SearchResultsSection.js +3 -3
  420. package/dist/features/search/components/SearchView.js +1 -1
  421. package/dist/features/search/hooks/useNavSuggestions.js +2 -1
  422. package/dist/features/search/hooks/useSearch.js +2 -2
  423. package/dist/features/search/schemas/index.d.ts +3 -3
  424. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  425. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  426. package/dist/features/seller/components/QuickProductForm.js +1 -1
  427. package/dist/features/seller/components/SellerAddressesView.js +4 -4
  428. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +3 -3
  429. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  430. package/dist/features/seller/components/SellerArtView.js +11 -11
  431. package/dist/features/seller/components/SellerAuctionsView.js +11 -11
  432. package/dist/features/seller/components/SellerBidsView.js +3 -3
  433. package/dist/features/seller/components/SellerBundlesView.js +12 -12
  434. package/dist/features/seller/components/SellerClassifiedView.js +11 -11
  435. package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
  436. package/dist/features/seller/components/SellerDigitalCodesView.js +11 -11
  437. package/dist/features/seller/components/SellerFeaturesView.js +4 -4
  438. package/dist/features/seller/components/SellerLiveView.js +11 -11
  439. package/dist/features/seller/components/SellerOffersPanel.js +3 -2
  440. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  441. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  442. package/dist/features/seller/components/SellerPayoutRequestView.js +6 -5
  443. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -4
  444. package/dist/features/seller/components/SellerPreOrdersView.js +1 -1
  445. package/dist/features/seller/components/SellerPrizeDrawsView.js +1 -1
  446. package/dist/features/seller/components/SellerProductShell.js +20 -6
  447. package/dist/features/seller/components/SellerProductsCards.js +3 -3
  448. package/dist/features/seller/components/SellerProductsView.js +4 -4
  449. package/dist/features/seller/components/SellerReviewsView.js +7 -6
  450. package/dist/features/seller/components/SellerShippingView.js +2 -1
  451. package/dist/features/seller/components/SellerSidebar.js +5 -5
  452. package/dist/features/seller/components/SellerStickersView.js +11 -11
  453. package/dist/features/seller/components/SellerTemplatesView.js +1 -1
  454. package/dist/features/seller/schemas/index.d.ts +20 -20
  455. package/dist/features/server-errors/schemas/index.d.ts +6 -6
  456. package/dist/features/shell/CommandPalette.d.ts +27 -0
  457. package/dist/features/shell/CommandPalette.js +92 -0
  458. package/dist/features/shell/FormShell.js +4 -3
  459. package/dist/features/shell/QuickFormDrawer.js +3 -2
  460. package/dist/features/shell/StepForm.js +2 -2
  461. package/dist/features/shell/index.d.ts +2 -0
  462. package/dist/features/shell/index.js +1 -0
  463. package/dist/features/shipments/components/AdminShipmentEditorView.d.ts +7 -0
  464. package/dist/features/shipments/components/AdminShipmentEditorView.js +123 -0
  465. package/dist/features/shipments/components/AdminShipmentLotItemsView.d.ts +6 -0
  466. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +96 -0
  467. package/dist/features/shipments/components/AdminShipmentProjectionsView.d.ts +9 -0
  468. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +44 -0
  469. package/dist/features/shipments/components/AdminShipmentsView.d.ts +8 -0
  470. package/dist/features/shipments/components/AdminShipmentsView.js +82 -0
  471. package/dist/features/shipments/components/ShipmentItemLinkModal.d.ts +15 -0
  472. package/dist/features/shipments/components/ShipmentItemLinkModal.js +37 -0
  473. package/dist/features/shipments/hooks/useShipments.d.ts +69 -0
  474. package/dist/features/shipments/hooks/useShipments.js +96 -0
  475. package/dist/features/shipments/index.d.ts +10 -0
  476. package/dist/features/shipments/index.js +7 -0
  477. package/dist/features/shipments/manifest.d.ts +2 -0
  478. package/dist/features/shipments/manifest.js +26 -0
  479. package/dist/features/shipments/repository/shipment-items.repository.d.ts +56 -0
  480. package/dist/features/shipments/repository/shipment-items.repository.js +78 -0
  481. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +48 -0
  482. package/dist/features/shipments/repository/shipment-lots.repository.js +55 -0
  483. package/dist/features/shipments/repository/shipments.repository.d.ts +50 -0
  484. package/dist/features/shipments/repository/shipments.repository.js +77 -0
  485. package/dist/features/shipments/schemas/firestore.d.ts +150 -0
  486. package/dist/features/shipments/schemas/firestore.js +76 -0
  487. package/dist/features/shipments/schemas/index.d.ts +2 -0
  488. package/dist/features/shipments/schemas/index.js +2 -0
  489. package/dist/features/shipments/schemas/validation.d.ts +350 -0
  490. package/dist/features/shipments/schemas/validation.js +96 -0
  491. package/dist/features/shipments/utils/cost-allocation.d.ts +25 -0
  492. package/dist/features/shipments/utils/cost-allocation.js +83 -0
  493. package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
  494. package/dist/features/stores/components/InteractiveStoreCard.js +2 -2
  495. package/dist/features/stores/components/StoreAboutView.js +1 -1
  496. package/dist/features/stores/components/StoreAuctionsListing.js +3 -3
  497. package/dist/features/stores/components/StoreAuctionsView.js +1 -1
  498. package/dist/features/stores/components/StoreCapabilitiesGuideView.js +1 -1
  499. package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
  500. package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
  501. package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
  502. package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
  503. package/dist/features/stores/components/StoreGuideHubView.js +2 -2
  504. package/dist/features/stores/components/StoreHeader.js +4 -4
  505. package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
  506. package/dist/features/stores/components/StoreNavTabs.js +2 -2
  507. package/dist/features/stores/components/StoreOrdersGuideView.js +1 -1
  508. package/dist/features/stores/components/StorePreOrdersListing.js +3 -3
  509. package/dist/features/stores/components/StoreProductsListing.js +1 -1
  510. package/dist/features/stores/components/StoreReviewsListing.js +2 -2
  511. package/dist/features/stores/components/StoreReviewsView.js +1 -1
  512. package/dist/features/stores/components/StoreSettingsGuideView.js +1 -1
  513. package/dist/features/stores/components/StoresIndexListing.js +9 -3
  514. package/dist/features/stores/schemas/index.d.ts +10 -10
  515. package/dist/features/support/schemas/index.d.ts +22 -22
  516. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -3
  517. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +1 -1
  518. package/dist/features/wishlist/hooks/useWishlistCount.js +1 -2
  519. package/dist/index.d.ts +44 -1
  520. package/dist/index.js +37 -1
  521. package/dist/next/routing/route-map.d.ts +18 -0
  522. package/dist/next/routing/route-map.js +9 -0
  523. package/dist/react/hooks/useVisualViewportInset.d.ts +1 -0
  524. package/dist/react/hooks/useVisualViewportInset.js +59 -0
  525. package/dist/react/index.d.ts +1 -0
  526. package/dist/react/index.js +1 -0
  527. package/dist/repositories/index.d.ts +5 -0
  528. package/dist/repositories/index.js +5 -0
  529. package/dist/schemas/registry.d.ts +398 -364
  530. package/dist/schemas/sieve.d.ts +2 -2
  531. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  532. package/dist/schemas/webhooks/razorpay.d.ts +100 -100
  533. package/dist/seed/_helpers/media.js +1 -0
  534. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  535. package/dist/seed/catalogue-seed-data.d.ts +2 -0
  536. package/dist/seed/catalogue-seed-data.js +112 -0
  537. package/dist/seed/grouped-listings-seed-data.d.ts +5 -0
  538. package/dist/seed/homepage-sections-seed-data.js +0 -1
  539. package/dist/seed/index.d.ts +2 -0
  540. package/dist/seed/index.js +2 -0
  541. package/dist/seed/manifest.js +6 -0
  542. package/dist/seed/products-preorders-seed-data.d.ts +5 -0
  543. package/dist/seed/shipments-seed-data.d.ts +5 -0
  544. package/dist/seed/shipments-seed-data.js +185 -0
  545. package/dist/server.d.ts +4 -0
  546. package/dist/server.js +5 -0
  547. package/dist/styles.css +75 -19
  548. package/dist/tailwind-utilities.css +1 -1
  549. package/dist/tokens/index.d.ts +0 -2
  550. package/dist/tokens/index.js +0 -2
  551. package/dist/tokens/tokens.css +12 -2
  552. package/dist/ui/DataTable.js +4 -3
  553. package/dist/ui/components/Button.d.ts +4 -1
  554. package/dist/ui/components/Button.js +11 -5
  555. package/dist/ui/components/Checkbox.d.ts +9 -1
  556. package/dist/ui/components/Checkbox.js +5 -2
  557. package/dist/ui/components/ClaimCouponButton.js +2 -1
  558. package/dist/ui/components/ConfirmDeleteModal.style.css +1 -1
  559. package/dist/ui/components/Drawer.style.css +13 -1
  560. package/dist/ui/components/Dropdown.style.css +2 -2
  561. package/dist/ui/components/FilterDrawer.d.ts +4 -1
  562. package/dist/ui/components/FilterDrawer.js +8 -2
  563. package/dist/ui/components/Form.d.ts +1 -1
  564. package/dist/ui/components/Form.js +2 -2
  565. package/dist/ui/components/FormActionBar.style.css +6 -1
  566. package/dist/ui/components/IconButton.d.ts +6 -1
  567. package/dist/ui/components/IconButton.js +5 -2
  568. package/dist/ui/components/IconButton.style.css +11 -0
  569. package/dist/ui/components/ImageGallery.style.css +2 -0
  570. package/dist/ui/components/ImageLightbox.style.css +1 -0
  571. package/dist/ui/components/ListingFilterDrawer.d.ts +4 -1
  572. package/dist/ui/components/ListingFilterDrawer.js +4 -3
  573. package/dist/ui/components/ListingLayout.style.css +2 -2
  574. package/dist/ui/components/Modal.style.css +1 -1
  575. package/dist/ui/components/Pagination.d.ts +5 -1
  576. package/dist/ui/components/Pagination.js +4 -2
  577. package/dist/ui/components/RowActionMenu.js +1 -1
  578. package/dist/ui/components/RowActionMenu.style.css +1 -1
  579. package/dist/ui/components/Select.d.ts +6 -1
  580. package/dist/ui/components/Select.js +18 -13
  581. package/dist/ui/components/Select.style.css +1 -1
  582. package/dist/ui/components/Semantic.d.ts +13 -0
  583. package/dist/ui/components/Semantic.js +16 -3
  584. package/dist/ui/components/SideDrawer.style.css +16 -4
  585. package/dist/ui/components/SideModal.style.css +1 -1
  586. package/dist/ui/components/StickyToolbar.d.ts +3 -2
  587. package/dist/ui/components/StickyToolbar.js +1 -1
  588. package/dist/ui/components/Textarea.d.ts +5 -0
  589. package/dist/ui/components/Textarea.js +8 -4
  590. package/dist/ui/components/Toast.style.css +3 -0
  591. package/dist/ui/components/UnsavedChangesModal.style.css +1 -1
  592. package/dist/ui/components/surface-tokens.d.ts +121 -113
  593. package/dist/ui/components/surface-tokens.js +110 -104
  594. package/dist/ui/forms/FormShell.d.ts +8 -27
  595. package/dist/ui/forms/FormShell.js +1 -194
  596. package/dist/ui/forms/index.d.ts +2 -2
  597. package/dist/ui/forms/index.js +1 -1
  598. package/dist/ui/index.d.ts +8 -4
  599. package/dist/ui/index.js +4 -2
  600. package/dist/utils/id-generators.d.ts +27 -0
  601. package/dist/utils/id-generators.js +45 -0
  602. package/dist/utils/number.formatter.d.ts +7 -0
  603. package/dist/utils/number.formatter.js +9 -0
  604. package/dist/validation/schemas.d.ts +5 -5
  605. package/package.json +1 -1
@@ -21,7 +21,6 @@ function MaskedInput({ label, value, onChange, placeholder, helperText, }) {
21
21
  return (_jsxs(Div, { className: "relative", children: [_jsx(Input, { label: label, value: value, onChange: (e) => onChange(e.target.value), type: revealed ? "text" : "password", placeholder: placeholder, helperText: helperText }), _jsx(Button, { type: "button", variant: "ghost", textSize: "xs", textColor: "faint", paddingX: "none", paddingY: "none", onClick: () => setRevealed((r) => !r), className: "absolute right-3 top-8", children: revealed ? "Hide" : "Reveal" })] }));
22
22
  }
23
23
  const NOTIF_CHANNEL_INDENT = "space-y-4 pl-4 border-l-2 border-[var(--appkit-color-border)]";
24
- const CLS_TEXTAREA = "w-full rounded-md border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] p-3 text-sm text-[var(--appkit-color-text-muted)] resize-y focus:outline-none focus:ring-2 focus:ring-blue-500";
25
24
  const PRIORITY_OPTIONS = [
26
25
  { label: "Low (send all)", value: "low" },
27
26
  { label: "Normal", value: "normal" },
@@ -109,6 +108,8 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
109
108
  el.style.opacity = String(watermarkOpacity / 100);
110
109
  }, [watermarkSize, watermarkOpacity]);
111
110
  // ⑦ Fees — all read/written under commissions key
111
+ const [laborHourlyRatePaise, setLaborHourlyRatePaise] = React.useState(20000);
112
+ const [laborMaxHoursPerDay, setLaborMaxHoursPerDay] = React.useState(6);
112
113
  const [platformFeePercent, setPlatformFeePercent] = React.useState(5);
113
114
  const [gstPercent, setGstPercent] = React.useState(18);
114
115
  const [minimumTransactionFee, setMinimumTransactionFee] = React.useState(0);
@@ -246,6 +247,8 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
246
247
  setPreOrderListingFee(s.commissions?.preOrderListingFee ?? 0);
247
248
  setFeaturedSlotFee(s.commissions?.featuredSlotFee ?? 999);
248
249
  setPromotedSlotFee(s.commissions?.promotedSlotFee ?? 499);
250
+ setLaborHourlyRatePaise(s.laborRate?.hourlyRatePaise ?? 20000);
251
+ setLaborMaxHoursPerDay(s.laborRate?.maxHoursPerDay ?? 6);
249
252
  setRazorpayKeyId(s.credentialsMasked?.razorpayKeyId ?? "");
250
253
  setRazorpaySecret(s.credentialsMasked?.razorpaySecret ?? "");
251
254
  setSmtpHost(s.emailSettings?.host ?? "");
@@ -355,6 +358,9 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
355
358
  const feesMutation = useSave("Fees", () => ({
356
359
  commissions: { platformFeePercent, gstPercent, minimumTransactionFee, gatewayFeePercent, payoutHoldDays, minPayoutAmount, auctionListingFee, preOrderListingFee, featuredSlotFee, promotedSlotFee },
357
360
  }));
361
+ const laborRateMutation = useSave("Procurement", () => ({
362
+ laborRate: { hourlyRatePaise: laborHourlyRatePaise, maxHoursPerDay: laborMaxHoursPerDay },
363
+ }));
358
364
  const integrationsMutation = useSave("Integrations", () => ({
359
365
  credentials: {
360
366
  razorpayKeyId, razorpaySecret, smtpPassword,
@@ -431,7 +437,8 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
431
437
  ["legal", "⑫ Legal"],
432
438
  ["whatsapp", "⑬ WhatsApp"],
433
439
  ["notifications", "⑭ Notifications"],
434
- ].map(([value, label]) => (_jsx(TabsTrigger, { value: value, children: label }, value))) }), _jsx(TabsContent, { value: "about", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); aboutMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Override the About page hero and mission text. Leave blank to use the platform defaults." }), _jsx(Input, { label: "Hero title", value: aboutTitle, onChange: (e) => setAboutTitle(e.target.value), placeholder: "About LetItRip" }), _jsx(Input, { label: "Hero subtitle", value: aboutSubtitle, onChange: (e) => setAboutSubtitle(e.target.value), placeholder: "Connecting buyers, sellers, and bidders in one vibrant marketplace" }), _jsx(Input, { label: "Mission section title", value: aboutMissionTitle, onChange: (e) => setAboutMissionTitle(e.target.value), placeholder: "Our Mission" }), _jsxs(_Fragment, { children: [_jsx(Text, { className: "mb-1", color: "muted", size: "sm", weight: "medium", children: "Mission text" }), _jsx("textarea", { value: aboutMissionText, onChange: (e) => setAboutMissionText(e.target.value), placeholder: "LetItRip was built to democratise commerce\u2026", rows: 4, className: CLS_TEXTAREA })] }), _jsx(Input, { label: "CTA banner title", value: aboutCtaTitle, onChange: (e) => setAboutCtaTitle(e.target.value), placeholder: "Ready to get started?" }), _jsx(GroupSaveButton, { isPending: aboutMutation.isPending })] }) }), _jsx(TabsContent, { value: "branding", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); brandingMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Input, { label: "Site name", value: siteName, onChange: (e) => setSiteName(e.target.value), placeholder: "LetItRip" }), _jsx(Input, { label: "Tagline", value: tagline, onChange: (e) => setTagline(e.target.value), placeholder: "India's Largest Collectibles Marketplace" }), _jsx(ImageUpload, { label: "Logo", currentImage: logoUrl, onUpload: (file) => upload(file, "store"), onChange: setLogoUrl }), _jsx(ImageUpload, { label: "Favicon", currentImage: faviconUrl, onUpload: (file) => upload(file, "store"), onChange: setFaviconUrl }), _jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "Maintenance mode", checked: maintenanceMode, onChange: setMaintenanceMode }), _jsx(Input, { label: "Maintenance message", value: maintenanceMessage, onChange: (e) => setMaintenanceMessage(e.target.value), placeholder: "We're back soon.", disabled: !maintenanceMode })] }), _jsx(GroupSaveButton, { isPending: brandingMutation.isPending })] }) }), _jsx(TabsContent, { value: "appearance", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); appearanceMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Sets the background behind the public shell, dashboard sidebars, and any Section/Card that opts into it. Leave the value blank for a plain surface." }), _jsxs(Grid, { cols: 2, gap: "lg", children: [_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Light mode" }), _jsx(Select, { label: "Type", options: BG_TYPE_OPTIONS, value: lightBgType, onValueChange: (v) => setLightBgType(v) }), lightBgType === "color" ? (_jsx(Input, { type: "color", label: "Color", value: lightBgValue || "#ffffff", onChange: (e) => setLightBgValue(e.target.value), className: "h-10 w-full cursor-pointer", bare: true }) /* audit-hex-tokens-ok: native color picker requires literal hex string fallback */) : lightBgType === "gradient" ? (_jsx(Textarea, { label: "CSS gradient expression", rows: 2, value: lightBgValue, onChange: (e) => setLightBgValue(e.target.value), placeholder: "linear-gradient(...)" })) : (_jsx(MediaUploadField, { label: lightBgType === "video" ? "Background video" : "Background image", kind: lightBgType === "video" ? "video" : "image", value: lightBgValue, onChange: setLightBgValue, onUpload: (file) => upload(file, "store") })), _jsx(Toggle, { label: "Dim overlay", checked: lightBgOverlayEnabled, onChange: setLightBgOverlayEnabled }), lightBgOverlayEnabled && (_jsxs(_Fragment, { children: [_jsx(Input, { type: "color", label: "Overlay color", value: lightBgOverlayColor, onChange: (e) => setLightBgOverlayColor(e.target.value), className: "h-10 w-full cursor-pointer", bare: true }), " ", _jsx(Slider, { label: "Overlay opacity", min: 0, max: 100, value: lightBgOverlayOpacity, onChange: setLightBgOverlayOpacity })] })), _jsx(Text, { size: "xs", color: "muted", children: "Preview" }), _jsx(Div, { className: "relative h-24 w-full", overflow: "hidden", rounded: "md", border: "default", children: _jsx(BackgroundRenderer, { mode: "light", lightMode: {
440
+ ["procurement", " Procurement"],
441
+ ].map(([value, label]) => (_jsx(TabsTrigger, { value: value, children: label }, value))) }), _jsx(TabsContent, { value: "about", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); aboutMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Override the About page hero and mission text. Leave blank to use the platform defaults." }), _jsx(Input, { label: "Hero title", value: aboutTitle, onChange: (e) => setAboutTitle(e.target.value), placeholder: "About LetItRip" }), _jsx(Input, { label: "Hero subtitle", value: aboutSubtitle, onChange: (e) => setAboutSubtitle(e.target.value), placeholder: "Connecting buyers, sellers, and bidders in one vibrant marketplace" }), _jsx(Input, { label: "Mission section title", value: aboutMissionTitle, onChange: (e) => setAboutMissionTitle(e.target.value), placeholder: "Our Mission" }), _jsxs(_Fragment, { children: [_jsx(Text, { className: "mb-1", color: "muted", size: "sm", weight: "medium", children: "Mission text" }), _jsx(Textarea, { value: aboutMissionText, onChange: (e) => setAboutMissionText(e.target.value), placeholder: "LetItRip was built to democratise commerce\u2026", rows: 4 })] }), _jsx(Input, { label: "CTA banner title", value: aboutCtaTitle, onChange: (e) => setAboutCtaTitle(e.target.value), placeholder: "Ready to get started?" }), _jsx(GroupSaveButton, { isPending: aboutMutation.isPending })] }) }), _jsx(TabsContent, { value: "branding", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); brandingMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Input, { label: "Site name", value: siteName, onChange: (e) => setSiteName(e.target.value), placeholder: "LetItRip" }), _jsx(Input, { label: "Tagline", value: tagline, onChange: (e) => setTagline(e.target.value), placeholder: "India's Largest Collectibles Marketplace" }), _jsx(ImageUpload, { label: "Logo", currentImage: logoUrl, onUpload: (file) => upload(file, "store"), onChange: setLogoUrl }), _jsx(ImageUpload, { label: "Favicon", currentImage: faviconUrl, onUpload: (file) => upload(file, "store"), onChange: setFaviconUrl }), _jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "Maintenance mode", checked: maintenanceMode, onChange: setMaintenanceMode }), _jsx(Input, { label: "Maintenance message", value: maintenanceMessage, onChange: (e) => setMaintenanceMessage(e.target.value), placeholder: "We're back soon.", disabled: !maintenanceMode })] }), _jsx(GroupSaveButton, { isPending: brandingMutation.isPending })] }) }), _jsx(TabsContent, { value: "appearance", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); appearanceMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Sets the background behind the public shell, dashboard sidebars, and any Section/Card that opts into it. Leave the value blank for a plain surface." }), _jsxs(Grid, { cols: 2, gap: "lg", children: [_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Light mode" }), _jsx(Select, { label: "Type", options: BG_TYPE_OPTIONS, value: lightBgType, onValueChange: (v) => setLightBgType(v) }), lightBgType === "color" ? (_jsx(Input, { type: "color", label: "Color", value: lightBgValue || "#ffffff", onChange: (e) => setLightBgValue(e.target.value), className: "h-10 w-full cursor-pointer", bare: true }) /* audit-hex-tokens-ok: native color picker requires literal hex string fallback */) : lightBgType === "gradient" ? (_jsx(Textarea, { label: "CSS gradient expression", rows: 2, value: lightBgValue, onChange: (e) => setLightBgValue(e.target.value), placeholder: "linear-gradient(...)" })) : (_jsx(MediaUploadField, { label: lightBgType === "video" ? "Background video" : "Background image", kind: lightBgType === "video" ? "video" : "image", value: lightBgValue, onChange: setLightBgValue, onUpload: (file) => upload(file, "store") })), _jsx(Toggle, { label: "Dim overlay", checked: lightBgOverlayEnabled, onChange: setLightBgOverlayEnabled }), lightBgOverlayEnabled && (_jsxs(_Fragment, { children: [_jsx(Input, { type: "color", label: "Overlay color", value: lightBgOverlayColor, onChange: (e) => setLightBgOverlayColor(e.target.value), className: "h-10 w-full cursor-pointer", bare: true }), " ", _jsx(Slider, { label: "Overlay opacity", min: 0, max: 100, value: lightBgOverlayOpacity, onChange: setLightBgOverlayOpacity })] })), _jsx(Text, { size: "xs", color: "muted", children: "Preview" }), _jsx(Div, { className: "relative h-24 w-full", overflow: "hidden", rounded: "md", border: "default", children: _jsx(BackgroundRenderer, { mode: "light", lightMode: {
435
442
  type: lightBgType,
436
443
  value: lightBgValue,
437
444
  overlay: { enabled: lightBgOverlayEnabled, color: lightBgOverlayColor, opacity: lightBgOverlayOpacity / 100 },
@@ -442,7 +449,7 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
442
449
  } }) })] })] }), _jsx(GroupSaveButton, { isPending: appearanceMutation.isPending })] }) }), _jsx(TabsContent, { value: "themes", children: _jsxs(Form, { onSubmit: (e) => {
443
450
  e.preventDefault();
444
451
  themeMutation.mutate();
445
- }, className: "pt-4", spacing: "md", children: [_jsx(ThemeManagerView, { value: themeRegistry, onChange: setThemeRegistry, previewOrigin: "/" }), _jsx(GroupSaveButton, { isPending: themeMutation.isPending })] }) }), _jsx(TabsContent, { value: "announcement", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); announcementMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Toggle, { label: "Show announcement bar", checked: announcementEnabled, onChange: setAnnouncementEnabled }), _jsx(Input, { label: "Announcement text", value: announcementText, onChange: (e) => setAnnouncementText(e.target.value), placeholder: "\uD83C\uDF89 Free shipping on orders \u20B9999+", disabled: !announcementEnabled }), _jsx(Input, { label: "Link URL (optional)", value: announcementLink, onChange: (e) => setAnnouncementLink(e.target.value), placeholder: String(ROUTES.PUBLIC.PRODUCTS), disabled: !announcementEnabled }), _jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", className: "mb-1", children: "Background color" }), _jsx(Input, { type: "color", value: announcementBg || "#1d4ed8", onChange: (e) => setAnnouncementBg(e.target.value), className: "h-10 w-32 cursor-pointer", bare: true, disabled: !announcementEnabled }), " "] }), _jsx(GroupSaveButton, { isPending: announcementMutation.isPending })] }) }), _jsx(TabsContent, { value: "seo", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); seoMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Input, { label: "Default meta title", value: seoTitle, onChange: (e) => setSeoTitle(e.target.value), placeholder: "LetItRip \u2014 Buy, Sell & Auction Collectibles in India", maxLength: 60, helperText: "Max 60 chars. Use {page} token for dynamic insertion." }), _jsx(Input, { label: "Default meta description", value: seoDescription, onChange: (e) => setSeoDescription(e.target.value), placeholder: "India's largest collectibles marketplace\u2026", maxLength: 160, helperText: "Max 160 chars." }), _jsx(ImageUpload, { label: "Default OG image", currentImage: seoOgImage, onUpload: (file) => upload(file, "store"), onChange: setSeoOgImage }), _jsx(Input, { label: "Canonical base URL", value: canonicalUrl, onChange: (e) => setCanonicalUrl(e.target.value), placeholder: "https://letitrip.in" }), _jsx(Toggle, { label: "Robots noindex (disables search indexing \u2014 use carefully)", checked: seoNoIndex, onChange: setSeoNoIndex }), _jsx(GroupSaveButton, { isPending: seoMutation.isPending })] }) }), _jsx(TabsContent, { value: "contact", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); contactMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Support email", value: supportEmail, onChange: (e) => setSupportEmail(e.target.value), type: "email", placeholder: "support@letitrip.in" }), _jsx(Input, { label: "Support phone", value: supportPhone, onChange: (e) => setSupportPhone(e.target.value), placeholder: "+91 XXXXX XXXXX" })] }), _jsx(Input, { label: "Physical address", value: supportAddress, onChange: (e) => setSupportAddress(e.target.value), placeholder: "Mumbai, Maharashtra, India" }), _jsx(Input, { label: "Support hours", value: supportHours, onChange: (e) => setSupportHours(e.target.value), placeholder: "Mon\u2013Fri, 10 AM \u2013 6 PM IST" }), _jsx(Text, { className: "pt-[0.5rem]", color: "muted", size: "sm", weight: "medium", children: "Social links" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Instagram URL", value: instagram, onChange: (e) => setInstagram(e.target.value), placeholder: "https://instagram.com/letitrip" }), _jsx(Input, { label: "Twitter / X URL", value: twitter, onChange: (e) => setTwitter(e.target.value), placeholder: "https://twitter.com/letitrip" }), _jsx(Input, { label: "Facebook URL", value: facebook, onChange: (e) => setFacebook(e.target.value), placeholder: "https://facebook.com/letitrip" }), _jsx(Input, { label: "YouTube URL", value: youtube, onChange: (e) => setYoutube(e.target.value), placeholder: "https://youtube.com/@letitrip" }), _jsx(Input, { label: "WhatsApp number", value: whatsapp, onChange: (e) => setWhatsapp(e.target.value), placeholder: "+91XXXXXXXXXX" }), _jsx(Input, { label: "LinkedIn URL", value: linkedin, onChange: (e) => setLinkedin(e.target.value), placeholder: "https://linkedin.com/company/letitrip" }), _jsx(Input, { label: "Pinterest URL", value: pinterest, onChange: (e) => setPinterest(e.target.value), placeholder: "https://pinterest.com/letitrip" })] }), _jsx(GroupSaveButton, { isPending: contactMutation.isPending })] }) }), _jsx(TabsContent, { value: "watermark", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); watermarkMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Select, { label: "Watermark type", options: [{ label: "Text", value: "text" }, { label: "Image", value: "image" }], value: watermarkType, onValueChange: (v) => setWatermarkType(v) }), watermarkType === "text" ? (_jsx(Input, { label: "Watermark text", value: watermarkText, onChange: (e) => setWatermarkText(e.target.value), placeholder: "letitrip.in" })) : (_jsx(ImageUpload, { label: "Watermark image", currentImage: watermarkImageUrl, onUpload: (file) => upload(file, "store"), onChange: setWatermarkImageUrl })), _jsx(Slider, { label: `Size — ${watermarkSize}% of image width`, value: watermarkSize, onChange: setWatermarkSize, min: 5, max: 100, step: 5 }), _jsx(Slider, { label: `Opacity — ${watermarkOpacity}%`, value: watermarkOpacity, onChange: setWatermarkOpacity, min: 5, max: 100, step: 5 }), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Preview (text watermark only)" }), _jsx(Row, { surface: "default", justify: "end", align: "end", className: `relative h-32 ${__O.hidden}`, rounded: "default", children: _jsx(Span, { ref: watermarkPreviewRef, weight: "medium", color: "faint", padding: "1", className: "select-none", children: watermarkText }) })] }), _jsx(GroupSaveButton, { isPending: watermarkMutation.isPending })] }) }), _jsx(TabsContent, { value: "fees", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); feesMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Platform fee \u2014 our cut (%)", helperText: "% charged on order value. Buyer pays this.", value: String(platformFeePercent), onChange: (e) => setPlatformFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "GST on platform fee (%)", helperText: "Applied to our fee only (not full order). Usually 18%.", value: String(gstPercent), onChange: (e) => setGstPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "Razorpay gateway cost (%)", helperText: "Gateway's own fee \u2014 absorbed by platform, not passed through.", value: String(gatewayFeePercent), onChange: (e) => setGatewayFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 10, step: 0.01 }), _jsx(Input, { label: "Minimum transaction fee (\u20B9)", helperText: "Per-transaction floor. Total charge will never be below base + this.", value: String(minimumTransactionFee), onChange: (e) => setMinimumTransactionFee(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Seller payout hold (days)", value: String(payoutHoldDays), onChange: (e) => setPayoutHoldDays(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Minimum payout amount (\u20B9)", value: String(minPayoutAmount), onChange: (e) => setMinPayoutAmount(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Auction listing fee (\u20B9)", value: String(auctionListingFee), onChange: (e) => setAuctionListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Pre-order listing fee (\u20B9)", value: String(preOrderListingFee), onChange: (e) => setPreOrderListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Featured slot fee (\u20B9)", value: String(featuredSlotFee), onChange: (e) => setFeaturedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Promoted slot fee (\u20B9)", value: String(promotedSlotFee), onChange: (e) => setPromotedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 })] }), _jsx(GroupSaveButton, { isPending: feesMutation.isPending })] }) }), _jsx(TabsContent, { value: "integrations", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); integrationsMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Keys are masked in transit and stored encrypted. Click Reveal to view." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Razorpay" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Razorpay Key ID", value: razorpayKeyId, onChange: setRazorpayKeyId, placeholder: "rzp_live_\u2026" }), _jsx(MaskedInput, { label: "Razorpay Secret", value: razorpaySecret, onChange: setRazorpaySecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "SMTP / Email" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "SMTP host", value: smtpHost, onChange: (e) => setSmtpHost(e.target.value), placeholder: "smtp.sendgrid.net" }), _jsx(Input, { label: "SMTP port", value: smtpPort, onChange: (e) => setSmtpPort(e.target.value), type: "number", placeholder: "587" }), _jsx(Input, { label: "SMTP user", value: smtpUser, onChange: (e) => setSmtpUser(e.target.value), placeholder: "apikey" }), _jsx(MaskedInput, { label: "SMTP password", value: smtpPassword, onChange: setSmtpPassword, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] }), _jsx(Input, { label: "From address", value: smtpFrom, onChange: (e) => setSmtpFrom(e.target.value), placeholder: "noreply@letitrip.in", type: "email" })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Analytics & Tracking" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Google Analytics ID", value: gaMeasurementId, onChange: (e) => setGaMeasurementId(e.target.value), placeholder: "G-XXXXXXXXXX" }), _jsx(Input, { label: "Facebook Pixel ID", value: fbPixelId, onChange: (e) => setFbPixelId(e.target.value), placeholder: "XXXXXXXXXXXXXXXX" }), _jsx(Input, { label: "GTM Container ID", value: gtmContainerId, onChange: (e) => setGtmContainerId(e.target.value), placeholder: "GTM-XXXXXXX" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Meta (Instagram & Facebook Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Used by the Social Feed section to fetch Instagram and Facebook posts via Meta Graph API v19." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Page Access Token", value: metaPageAccessToken, onChange: setMetaPageAccessToken, placeholder: "EAAxxxxxxx\u2026" }), _jsx(Input, { label: "Page ID (or handle)", value: metaPageId, onChange: (e) => setMetaPageId(e.target.value), placeholder: "letitrip" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "TikTok for Developers (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials + long-lived access token from TikTok for Developers. Used to list your account's public videos." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client Key", value: tiktokClientKey, onChange: setTiktokClientKey, placeholder: "aw\u2026" }), _jsx(MaskedInput, { label: "Client Secret", value: tiktokClientSecret, onChange: setTiktokClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "Access Token (long-lived)", value: tiktokAccessToken, onChange: setTiktokAccessToken, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "DeviantArt OAuth2 (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials for DeviantArt gallery fetching (client-credentials OAuth2 flow \u2014 no user login required)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client ID", value: deviantartClientId, onChange: setDeviantartClientId, placeholder: "1234" }), _jsx(MaskedInput, { label: "Client Secret", value: deviantartClientSecret, onChange: setDeviantartClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsx(GroupSaveButton, { isPending: integrationsMutation.isPending })] }) }), _jsx(TabsContent, { value: "shipping", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); shippingMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Payment methods" }), _jsx(Toggle, { label: "Razorpay (online card/UPI) enabled \u2014 disabled by default, manual payment is the default", checked: razorpayEnabled, onChange: setRazorpayEnabled }), _jsx(Toggle, { label: "Manual UPI/bank transfer enabled", checked: upiManualEnabled, onChange: setUpiManualEnabled }), _jsx(Toggle, { label: "Cash on delivery (COD) enabled", checked: codEnabled, onChange: setCodEnabled }), _jsx(Input, { label: "Free shipping threshold (\u20B9)", value: String(freeShippingThreshold), onChange: (e) => setFreeShippingThreshold(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Orders above this amount get free shipping." }), _jsx(Select, { label: "Default carrier", options: CARRIER_OPTIONS, value: defaultCarrier, onValueChange: setDefaultCarrier }), _jsx(Input, { label: "Max delivery radius (km, 0 = no limit)", value: String(maxDeliveryRadius), onChange: (e) => setMaxDeliveryRadius(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(GroupSaveButton, { isPending: shippingMutation.isPending })] }) }), _jsx(TabsContent, { value: "auction", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); auctionMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Input, { label: "Minimum bid increment (\u20B9)", value: String(minBidIncrement), onChange: (e) => setMinBidIncrement(parseInt(e.target.value) || 0), type: "number", min: 1, helperText: "Global default \u2014 individual auctions may override." }), _jsx(Input, { label: "Auto-extend window (minutes before end)", value: String(autoExtendWindow), onChange: (e) => setAutoExtendWindow(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Extend auction end time if a bid arrives within this window." }), _jsx(Input, { label: "Settlement grace period (hours)", value: String(settlementGrace), onChange: (e) => setSettlementGrace(parseInt(e.target.value) || 0), type: "number", min: 1, helperText: "Time winner has to pay before the auction is re-listed." }), _jsx(GroupSaveButton, { isPending: auctionMutation.isPending })] }) }), _jsx(TabsContent, { value: "limits", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); limitsMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Max products per store", value: String(maxProductsPerStore), onChange: (e) => setMaxProductsPerStore(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max images per product", value: String(maxImagesPerProduct), onChange: (e) => setMaxImagesPerProduct(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max video size (MB)", value: String(maxVideoSizeMb), onChange: (e) => setMaxVideoSizeMb(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max custom fields per product", value: String(maxCustomFields), onChange: (e) => setMaxCustomFields(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Max custom sections per product", value: String(maxCustomSections), onChange: (e) => setMaxCustomSections(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Order cancellation window (hours)", value: String(orderCancelWindow), onChange: (e) => setOrderCancelWindow(parseInt(e.target.value) || 0), type: "number", min: 0 })] }), _jsx(GroupSaveButton, { isPending: limitsMutation.isPending })] }) }), _jsx(TabsContent, { value: "whatsapp", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); whatsappMutation.mutate(); }, className: "pt-4", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Platform-level WhatsApp Business Cloud API credentials. Used for automated purchase announcements to admin numbers when orders are placed. Store owners configure their own credentials in Store \u2192 WhatsApp." }), _jsx(Input, { label: "Phone Number ID", value: waPhoneNumberId, onChange: (e) => setWaPhoneNumberId(e.target.value), placeholder: "987654321098765", helperText: "From Meta for Developers \u2192 App \u2192 WhatsApp \u2192 API Setup" }), _jsx(MaskedInput, { label: "Cloud API System User Token", value: waCloudApiToken, onChange: setWaCloudApiToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived system user access token with WhatsApp Business permissions" }), _jsx(Input, { label: "Admin Notify Numbers", value: waAdminNotifyNumbers, onChange: (e) => setWaAdminNotifyNumbers(e.target.value), placeholder: "919876543210,918765432109", helperText: "Comma-separated, digits-only, include country code. These receive a WhatsApp message when any order is placed." }), _jsx(GroupSaveButton, { isPending: whatsappMutation.isPending })] }) }), _jsx(TabsContent, { value: "notifications", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); notifChannelsMutation.mutate(); }, className: "pt-4", spacing: "lg", children: [_jsx(Text, { size: "xs", color: "muted", children: "In-app notifications are always on. Enable external channels below to let the platform fan out to email, WhatsApp, or SMS. Users can further restrict which types they receive." }), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsxs(Row, { justify: "between", gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "In-app (notification bell)" }), _jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-xs", children: "Always on" })] }), _jsx(Text, { size: "xs", color: "muted", children: "Displayed in the notification bell and inbox. Cannot be disabled." })] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "Email notifications", checked: notifEmailEnabled, onChange: setNotifEmailEnabled }), notifEmailEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send email", options: PRIORITY_OPTIONS, value: notifEmailMinPriority, onValueChange: setNotifEmailMinPriority }), _jsx(Text, { size: "xs", weight: "medium", color: "muted", className: "pt-[0.25rem]", children: "Resend API (for transactional email)" }), _jsx(MaskedInput, { label: "Resend API Key", value: resendApiKey, onChange: setResendApiKey, placeholder: "re_live_\u2026", helperText: "Get your key at resend.com \u2014 used for all transactional notifications." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "From email", value: notifFromEmail, onChange: (e) => setNotifFromEmail(e.target.value), placeholder: "noreply@letitrip.in", type: "email" }), _jsx(Input, { label: "From name", value: notifFromName, onChange: (e) => setNotifFromName(e.target.value), placeholder: "LetItRip" })] })] }))] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "WhatsApp notifications", checked: notifWhatsappEnabled, onChange: setNotifWhatsappEnabled }), notifWhatsappEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send WhatsApp", options: PRIORITY_OPTIONS, value: notifWhatsappMinPriority, onValueChange: setNotifWhatsappMinPriority }), _jsx(Toggle, { label: "Enable WhatsApp OTP (for login and verification)", checked: notifWhatsappOtpEnabled, onChange: setNotifWhatsappOtpEnabled }), _jsx(Text, { size: "xs", color: "muted", children: "WhatsApp credentials are configured in the WhatsApp tab (\u246C). OTP messages use the same phone number." })] }))] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "SMS notifications", checked: notifSmsEnabled, onChange: setNotifSmsEnabled }), notifSmsEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send SMS", options: PRIORITY_OPTIONS, value: notifSmsMinPriority, onValueChange: setNotifSmsMinPriority }), _jsx(Text, { size: "xs", color: "muted", children: "SMS gateway credentials (e.g. Twilio, MSG91) can be configured in the Integrations tab once an SMS provider is connected." })] }))] }), _jsx(GroupSaveButton, { isPending: notifChannelsMutation.isPending })] }) }), _jsx(TabsContent, { value: "legal", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); legalMutation.mutate(); }, className: "pt-4", spacing: "md", children: [[
452
+ }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(ThemeManagerView, { value: themeRegistry, onChange: setThemeRegistry, previewOrigin: "/" }), _jsx(GroupSaveButton, { isPending: themeMutation.isPending })] }) }), _jsx(TabsContent, { value: "announcement", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); announcementMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Toggle, { label: "Show announcement bar", checked: announcementEnabled, onChange: setAnnouncementEnabled }), _jsx(Input, { label: "Announcement text", value: announcementText, onChange: (e) => setAnnouncementText(e.target.value), placeholder: "\uD83C\uDF89 Free shipping on orders \u20B9999+", disabled: !announcementEnabled }), _jsx(Input, { label: "Link URL (optional)", value: announcementLink, onChange: (e) => setAnnouncementLink(e.target.value), placeholder: String(ROUTES.PUBLIC.PRODUCTS), disabled: !announcementEnabled }), _jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", className: "mb-1", children: "Background color" }), _jsx(Input, { type: "color", value: announcementBg || "#1d4ed8", onChange: (e) => setAnnouncementBg(e.target.value), className: "h-10 w-32 cursor-pointer", bare: true, disabled: !announcementEnabled }), " "] }), _jsx(GroupSaveButton, { isPending: announcementMutation.isPending })] }) }), _jsx(TabsContent, { value: "seo", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); seoMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Input, { label: "Default meta title", value: seoTitle, onChange: (e) => setSeoTitle(e.target.value), placeholder: "LetItRip \u2014 Buy, Sell & Auction Collectibles in India", maxLength: 60, helperText: "Max 60 chars. Use {page} token for dynamic insertion." }), _jsx(Input, { label: "Default meta description", value: seoDescription, onChange: (e) => setSeoDescription(e.target.value), placeholder: "India's largest collectibles marketplace\u2026", maxLength: 160, helperText: "Max 160 chars." }), _jsx(ImageUpload, { label: "Default OG image", currentImage: seoOgImage, onUpload: (file) => upload(file, "store"), onChange: setSeoOgImage }), _jsx(Input, { label: "Canonical base URL", value: canonicalUrl, onChange: (e) => setCanonicalUrl(e.target.value), placeholder: "https://letitrip.in" }), _jsx(Toggle, { label: "Robots noindex (disables search indexing \u2014 use carefully)", checked: seoNoIndex, onChange: setSeoNoIndex }), _jsx(GroupSaveButton, { isPending: seoMutation.isPending })] }) }), _jsx(TabsContent, { value: "contact", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); contactMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Support email", value: supportEmail, onChange: (e) => setSupportEmail(e.target.value), type: "email", placeholder: "support@letitrip.in" }), _jsx(Input, { label: "Support phone", value: supportPhone, onChange: (e) => setSupportPhone(e.target.value), placeholder: "+91 XXXXX XXXXX" })] }), _jsx(Input, { label: "Physical address", value: supportAddress, onChange: (e) => setSupportAddress(e.target.value), placeholder: "Mumbai, Maharashtra, India" }), _jsx(Input, { label: "Support hours", value: supportHours, onChange: (e) => setSupportHours(e.target.value), placeholder: "Mon\u2013Fri, 10 AM \u2013 6 PM IST" }), _jsx(Text, { className: "pt-[0.5rem]", color: "muted", size: "sm", weight: "medium", children: "Social links" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Instagram URL", value: instagram, onChange: (e) => setInstagram(e.target.value), placeholder: "https://instagram.com/letitrip" }), _jsx(Input, { label: "Twitter / X URL", value: twitter, onChange: (e) => setTwitter(e.target.value), placeholder: "https://twitter.com/letitrip" }), _jsx(Input, { label: "Facebook URL", value: facebook, onChange: (e) => setFacebook(e.target.value), placeholder: "https://facebook.com/letitrip" }), _jsx(Input, { label: "YouTube URL", value: youtube, onChange: (e) => setYoutube(e.target.value), placeholder: "https://youtube.com/@letitrip" }), _jsx(Input, { label: "WhatsApp number", value: whatsapp, onChange: (e) => setWhatsapp(e.target.value), placeholder: "+91XXXXXXXXXX" }), _jsx(Input, { label: "LinkedIn URL", value: linkedin, onChange: (e) => setLinkedin(e.target.value), placeholder: "https://linkedin.com/company/letitrip" }), _jsx(Input, { label: "Pinterest URL", value: pinterest, onChange: (e) => setPinterest(e.target.value), placeholder: "https://pinterest.com/letitrip" })] }), _jsx(GroupSaveButton, { isPending: contactMutation.isPending })] }) }), _jsx(TabsContent, { value: "watermark", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); watermarkMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Select, { label: "Watermark type", options: [{ label: "Text", value: "text" }, { label: "Image", value: "image" }], value: watermarkType, onValueChange: (v) => setWatermarkType(v) }), watermarkType === "text" ? (_jsx(Input, { label: "Watermark text", value: watermarkText, onChange: (e) => setWatermarkText(e.target.value), placeholder: "letitrip.in" })) : (_jsx(ImageUpload, { label: "Watermark image", currentImage: watermarkImageUrl, onUpload: (file) => upload(file, "store"), onChange: setWatermarkImageUrl })), _jsx(Slider, { label: `Size — ${watermarkSize}% of image width`, value: watermarkSize, onChange: setWatermarkSize, min: 5, max: 100, step: 5 }), _jsx(Slider, { label: `Opacity — ${watermarkOpacity}%`, value: watermarkOpacity, onChange: setWatermarkOpacity, min: 5, max: 100, step: 5 }), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Preview (text watermark only)" }), _jsx(Row, { surface: "default", justify: "end", align: "end", className: `relative h-32 ${__O.hidden}`, rounded: "default", children: _jsx(Span, { ref: watermarkPreviewRef, weight: "medium", color: "faint", padding: "1", className: "select-none", children: watermarkText }) })] }), _jsx(GroupSaveButton, { isPending: watermarkMutation.isPending })] }) }), _jsx(TabsContent, { value: "fees", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); feesMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Platform fee \u2014 our cut (%)", helperText: "% charged on order value. Buyer pays this.", value: String(platformFeePercent), onChange: (e) => setPlatformFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "GST on platform fee (%)", helperText: "Applied to our fee only (not full order). Usually 18%.", value: String(gstPercent), onChange: (e) => setGstPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "Razorpay gateway cost (%)", helperText: "Gateway's own fee \u2014 absorbed by platform, not passed through.", value: String(gatewayFeePercent), onChange: (e) => setGatewayFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 10, step: 0.01 }), _jsx(Input, { label: "Minimum transaction fee (\u20B9)", helperText: "Per-transaction floor. Total charge will never be below base + this.", value: String(minimumTransactionFee), onChange: (e) => setMinimumTransactionFee(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Seller payout hold (days)", value: String(payoutHoldDays), onChange: (e) => setPayoutHoldDays(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Minimum payout amount (\u20B9)", value: String(minPayoutAmount), onChange: (e) => setMinPayoutAmount(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Auction listing fee (\u20B9)", value: String(auctionListingFee), onChange: (e) => setAuctionListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Pre-order listing fee (\u20B9)", value: String(preOrderListingFee), onChange: (e) => setPreOrderListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Featured slot fee (\u20B9)", value: String(featuredSlotFee), onChange: (e) => setFeaturedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Promoted slot fee (\u20B9)", value: String(promotedSlotFee), onChange: (e) => setPromotedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 })] }), _jsx(GroupSaveButton, { isPending: feesMutation.isPending })] }) }), _jsx(TabsContent, { value: "procurement", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); laborRateMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Used to compute each procurement shipment's labor cost (hours spent \u00D7 hourly rate) and its estimated processing time (hours spent \u00F7 max hours/day)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Hourly rate (\u20B9)", helperText: "Your effective hourly wage for sorting/categorizing/listing a shipment.", value: String(laborHourlyRatePaise / 100), onChange: (e) => setLaborHourlyRatePaise(Math.round((parseFloat(e.target.value) || 0) * 100)), type: "number", min: 0 }), _jsx(Input, { label: "Max hours per day", helperText: "Used only to project how many days a shipment's tracked hours will take.", value: String(laborMaxHoursPerDay), onChange: (e) => setLaborMaxHoursPerDay(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 24 })] }), _jsx(GroupSaveButton, { isPending: laborRateMutation.isPending })] }) }), _jsx(TabsContent, { value: "integrations", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); integrationsMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Keys are masked in transit and stored encrypted. Click Reveal to view." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Razorpay" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Razorpay Key ID", value: razorpayKeyId, onChange: setRazorpayKeyId, placeholder: "rzp_live_\u2026" }), _jsx(MaskedInput, { label: "Razorpay Secret", value: razorpaySecret, onChange: setRazorpaySecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "SMTP / Email" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "SMTP host", value: smtpHost, onChange: (e) => setSmtpHost(e.target.value), placeholder: "smtp.sendgrid.net" }), _jsx(Input, { label: "SMTP port", value: smtpPort, onChange: (e) => setSmtpPort(e.target.value), type: "number", placeholder: "587" }), _jsx(Input, { label: "SMTP user", value: smtpUser, onChange: (e) => setSmtpUser(e.target.value), placeholder: "apikey" }), _jsx(MaskedInput, { label: "SMTP password", value: smtpPassword, onChange: setSmtpPassword, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] }), _jsx(Input, { label: "From address", value: smtpFrom, onChange: (e) => setSmtpFrom(e.target.value), placeholder: "noreply@letitrip.in", type: "email" })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Analytics & Tracking" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Google Analytics ID", value: gaMeasurementId, onChange: (e) => setGaMeasurementId(e.target.value), placeholder: "G-XXXXXXXXXX" }), _jsx(Input, { label: "Facebook Pixel ID", value: fbPixelId, onChange: (e) => setFbPixelId(e.target.value), placeholder: "XXXXXXXXXXXXXXXX" }), _jsx(Input, { label: "GTM Container ID", value: gtmContainerId, onChange: (e) => setGtmContainerId(e.target.value), placeholder: "GTM-XXXXXXX" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Meta (Instagram & Facebook Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Used by the Social Feed section to fetch Instagram and Facebook posts via Meta Graph API v19." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Page Access Token", value: metaPageAccessToken, onChange: setMetaPageAccessToken, placeholder: "EAAxxxxxxx\u2026" }), _jsx(Input, { label: "Page ID (or handle)", value: metaPageId, onChange: (e) => setMetaPageId(e.target.value), placeholder: "letitrip" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "TikTok for Developers (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials + long-lived access token from TikTok for Developers. Used to list your account's public videos." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client Key", value: tiktokClientKey, onChange: setTiktokClientKey, placeholder: "aw\u2026" }), _jsx(MaskedInput, { label: "Client Secret", value: tiktokClientSecret, onChange: setTiktokClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "Access Token (long-lived)", value: tiktokAccessToken, onChange: setTiktokAccessToken, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "DeviantArt OAuth2 (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials for DeviantArt gallery fetching (client-credentials OAuth2 flow \u2014 no user login required)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client ID", value: deviantartClientId, onChange: setDeviantartClientId, placeholder: "1234" }), _jsx(MaskedInput, { label: "Client Secret", value: deviantartClientSecret, onChange: setDeviantartClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsx(GroupSaveButton, { isPending: integrationsMutation.isPending })] }) }), _jsx(TabsContent, { value: "shipping", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); shippingMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Payment methods" }), _jsx(Toggle, { label: "Razorpay (online card/UPI) enabled \u2014 disabled by default, manual payment is the default", checked: razorpayEnabled, onChange: setRazorpayEnabled }), _jsx(Toggle, { label: "Manual UPI/bank transfer enabled", checked: upiManualEnabled, onChange: setUpiManualEnabled }), _jsx(Toggle, { label: "Cash on delivery (COD) enabled", checked: codEnabled, onChange: setCodEnabled }), _jsx(Input, { label: "Free shipping threshold (\u20B9)", value: String(freeShippingThreshold), onChange: (e) => setFreeShippingThreshold(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Orders above this amount get free shipping." }), _jsx(Select, { label: "Default carrier", options: CARRIER_OPTIONS, value: defaultCarrier, onValueChange: setDefaultCarrier }), _jsx(Input, { label: "Max delivery radius (km, 0 = no limit)", value: String(maxDeliveryRadius), onChange: (e) => setMaxDeliveryRadius(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(GroupSaveButton, { isPending: shippingMutation.isPending })] }) }), _jsx(TabsContent, { value: "auction", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); auctionMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Input, { label: "Minimum bid increment (\u20B9)", value: String(minBidIncrement), onChange: (e) => setMinBidIncrement(parseInt(e.target.value) || 0), type: "number", min: 1, helperText: "Global default \u2014 individual auctions may override." }), _jsx(Input, { label: "Auto-extend window (minutes before end)", value: String(autoExtendWindow), onChange: (e) => setAutoExtendWindow(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Extend auction end time if a bid arrives within this window." }), _jsx(Input, { label: "Settlement grace period (hours)", value: String(settlementGrace), onChange: (e) => setSettlementGrace(parseInt(e.target.value) || 0), type: "number", min: 1, helperText: "Time winner has to pay before the auction is re-listed." }), _jsx(GroupSaveButton, { isPending: auctionMutation.isPending })] }) }), _jsx(TabsContent, { value: "limits", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); limitsMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Max products per store", value: String(maxProductsPerStore), onChange: (e) => setMaxProductsPerStore(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max images per product", value: String(maxImagesPerProduct), onChange: (e) => setMaxImagesPerProduct(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max video size (MB)", value: String(maxVideoSizeMb), onChange: (e) => setMaxVideoSizeMb(parseInt(e.target.value) || 0), type: "number", min: 1 }), _jsx(Input, { label: "Max custom fields per product", value: String(maxCustomFields), onChange: (e) => setMaxCustomFields(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Max custom sections per product", value: String(maxCustomSections), onChange: (e) => setMaxCustomSections(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Order cancellation window (hours)", value: String(orderCancelWindow), onChange: (e) => setOrderCancelWindow(parseInt(e.target.value) || 0), type: "number", min: 0 })] }), _jsx(GroupSaveButton, { isPending: limitsMutation.isPending })] }) }), _jsx(TabsContent, { value: "whatsapp", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); whatsappMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Platform-level WhatsApp Business Cloud API credentials. Used for automated purchase announcements to admin numbers when orders are placed. Store owners configure their own credentials in Store \u2192 WhatsApp." }), _jsx(Input, { label: "Phone Number ID", value: waPhoneNumberId, onChange: (e) => setWaPhoneNumberId(e.target.value), placeholder: "987654321098765", helperText: "From Meta for Developers \u2192 App \u2192 WhatsApp \u2192 API Setup" }), _jsx(MaskedInput, { label: "Cloud API System User Token", value: waCloudApiToken, onChange: setWaCloudApiToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived system user access token with WhatsApp Business permissions" }), _jsx(Input, { label: "Admin Notify Numbers", value: waAdminNotifyNumbers, onChange: (e) => setWaAdminNotifyNumbers(e.target.value), placeholder: "919876543210,918765432109", helperText: "Comma-separated, digits-only, include country code. These receive a WhatsApp message when any order is placed." }), _jsx(GroupSaveButton, { isPending: whatsappMutation.isPending })] }) }), _jsx(TabsContent, { value: "notifications", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); notifChannelsMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "lg", children: [_jsx(Text, { size: "xs", color: "muted", children: "In-app notifications are always on. Enable external channels below to let the platform fan out to email, WhatsApp, or SMS. Users can further restrict which types they receive." }), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsxs(Row, { justify: "between", gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "In-app (notification bell)" }), _jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-xs", children: "Always on" })] }), _jsx(Text, { size: "xs", color: "muted", children: "Displayed in the notification bell and inbox. Cannot be disabled." })] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "Email notifications", checked: notifEmailEnabled, onChange: setNotifEmailEnabled }), notifEmailEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send email", options: PRIORITY_OPTIONS, value: notifEmailMinPriority, onValueChange: setNotifEmailMinPriority }), _jsx(Text, { size: "xs", weight: "medium", color: "muted", className: "pt-[0.25rem]", children: "Resend API (for transactional email)" }), _jsx(MaskedInput, { label: "Resend API Key", value: resendApiKey, onChange: setResendApiKey, placeholder: "re_live_\u2026", helperText: "Get your key at resend.com \u2014 used for all transactional notifications." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "From email", value: notifFromEmail, onChange: (e) => setNotifFromEmail(e.target.value), placeholder: "noreply@letitrip.in", type: "email" }), _jsx(Input, { label: "From name", value: notifFromName, onChange: (e) => setNotifFromName(e.target.value), placeholder: "LetItRip" })] })] }))] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "WhatsApp notifications", checked: notifWhatsappEnabled, onChange: setNotifWhatsappEnabled }), notifWhatsappEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send WhatsApp", options: PRIORITY_OPTIONS, value: notifWhatsappMinPriority, onValueChange: setNotifWhatsappMinPriority }), _jsx(Toggle, { label: "Enable WhatsApp OTP (for login and verification)", checked: notifWhatsappOtpEnabled, onChange: setNotifWhatsappOtpEnabled }), _jsx(Text, { size: "xs", color: "muted", children: "WhatsApp credentials are configured in the WhatsApp tab (\u246C). OTP messages use the same phone number." })] }))] }), _jsxs(Stack, { gap: "md", rounded: "lg", border: "default", padding: "md", children: [_jsx(Toggle, { label: "SMS notifications", checked: notifSmsEnabled, onChange: setNotifSmsEnabled }), notifSmsEnabled && (_jsxs(Stack, { gap: "md", className: NOTIF_CHANNEL_INDENT, children: [_jsx(Select, { label: "Minimum priority to send SMS", options: PRIORITY_OPTIONS, value: notifSmsMinPriority, onValueChange: setNotifSmsMinPriority }), _jsx(Text, { size: "xs", color: "muted", children: "SMS gateway credentials (e.g. Twilio, MSG91) can be configured in the Integrations tab once an SMS provider is connected." })] }))] }), _jsx(GroupSaveButton, { isPending: notifChannelsMutation.isPending })] }) }), _jsx(TabsContent, { value: "legal", children: _jsxs(Form, { onSubmit: (e) => { e.preventDefault(); legalMutation.mutate(); }, className: "pt-[var(--appkit-space-4)]", spacing: "md", children: [[
446
453
  ["Terms of Service", termsHtml, setTermsHtml],
447
454
  ["Privacy Policy", privacyHtml, setPrivacyHtml],
448
455
  ["Refund Policy", refundHtml, setRefundHtml],
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useApiMutation } from "@mohasinac/appkit/client";
4
4
  import React from "react";
5
5
  import { useQueryClient } from "@tanstack/react-query";
6
- import { Button, Details, Div, Form, FormActions, Label, Select, SideDrawer, Span, Stack, StackedViewShell, Summary, Toggle, useToast } from "../../../ui";
6
+ import { Button, Checkbox, Details, Div, Form, FormActions, Label, Select, SideDrawer, Span, Stack, StackedViewShell, Summary, Textarea, Toggle, useToast } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
8
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
9
  const CAPABILITY_GROUPS = [
@@ -47,7 +47,6 @@ const STATUS_OPTIONS = [
47
47
  { label: "Suspended", value: "suspended" },
48
48
  { label: "Rejected", value: "rejected" },
49
49
  ];
50
- const TEXTAREA_CHROME = "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500";
51
50
  // --- Component ---------------------------------------------------------------
52
51
  export function AdminStoreEditorView({ open, onClose, storeId, storeName, currentStatus, currentIsVerified, currentCapabilities, }) {
53
52
  const queryClient = useQueryClient();
@@ -99,12 +98,12 @@ export function AdminStoreEditorView({ open, onClose, storeId, storeName, curren
99
98
  },
100
99
  });
101
100
  const renderStatusSection = () => (_jsx(Select, { label: "Store status", options: STATUS_OPTIONS, value: storeStatus, onValueChange: setStoreStatus }));
102
- const renderNotesSection = () => (_jsxs(Stack, { gap: "xs", 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 })] }));
101
+ const renderNotesSection = () => (_jsxs(Stack, { gap: "xs", 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" })] }));
103
102
  const renderTogglesSection = () => (_jsxs(_Fragment, { children: [_jsx(Toggle, { label: "Verified store", checked: isVerified, onChange: setIsVerified }), _jsx(Toggle, { label: "Featured store", checked: isFeatured, onChange: setIsFeatured })] }));
104
- const renderSuspensionSection = () => storeStatus === "suspended" ? (_jsxs(Stack, { gap: "xs", 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;
103
+ const renderSuspensionSection = () => storeStatus === "suspended" ? (_jsxs(Stack, { gap: "xs", 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" })] })) : null;
105
104
  const renderCapabilitiesSection = () => (_jsxs(Stack, { gap: "sm", children: [_jsxs(Span, { size: "sm", weight: "medium", color: "muted", children: ["Capabilities", _jsxs(Span, { size: "xs", weight: "normal", className: "ml-2", color: "muted", children: ["(", capabilities.size, " active)"] })] }), _jsx(Div, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border)]", rounded: "xl", border: "default", children: CAPABILITY_GROUPS.map((group) => {
106
105
  const checked = group.caps.filter((c) => capabilities.has(c.key)).length;
107
- return (_jsxs(Details, { className: "group", children: [_jsxs(Summary, { paddingX: "x-sm", paddingY: "y-xs", weight: "semibold", color: "muted", layout: "flex", align: "center", justify: "between", className: "uppercase tracking-wide hover:bg-[var(--appkit-color-bg)] transition-colors", children: [_jsx(Span, { size: "xs", children: group.label }), _jsxs(Span, { size: "xs", weight: "normal", className: "normal-case", color: "faint", children: [checked, "/", group.caps.length] })] }), _jsx(Div, { layout: "grid", paddingY: "y-xs-tall", className: "grid-cols-2 gap-x-2 gap-y-1.5", surface: "muted", padding: "x-sm", children: group.caps.map((cap) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-xs text-[var(--appkit-color-text-muted)]", children: [_jsx("input", { type: "checkbox", checked: capabilities.has(cap.key), onChange: () => toggleCapability(cap.key), className: "h-3.5 w-3.5 rounded border-[var(--appkit-color-border)] accent-primary" }), cap.label] }, cap.key))) })] }, group.label));
106
+ return (_jsxs(Details, { className: "group", children: [_jsxs(Summary, { paddingX: "x-sm", paddingY: "y-xs", weight: "semibold", color: "muted", layout: "flex", align: "center", justify: "between", className: "uppercase tracking-wide hover:bg-[var(--appkit-color-bg)] transition-colors", children: [_jsx(Span, { size: "xs", children: group.label }), _jsxs(Span, { size: "xs", weight: "normal", className: "normal-case", color: "faint", children: [checked, "/", group.caps.length] })] }), _jsx(Div, { layout: "grid", paddingY: "y-xs-tall", className: "grid-cols-2 gap-x-2 gap-y-1.5", surface: "muted", padding: "x-sm", children: group.caps.map((cap) => (_jsxs("label", { className: "flex items-center gap-[var(--appkit-space-2)] cursor-pointer text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)]", children: [_jsx(Checkbox, { bare: true, checked: capabilities.has(cap.key), onChange: () => toggleCapability(cap.key), className: "h-3.5 w-3.5 rounded border-[var(--appkit-color-border)] accent-primary" }), cap.label] }, cap.key))) })] }, group.label));
108
107
  }) })] }));
109
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" })] }));
110
109
  return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: storeName ? `Manage: ${storeName}` : "Manage Store", children: _jsx(Form, { onSubmit: (e) => {
@@ -8,6 +8,7 @@ import { useQueryClient } from "@tanstack/react-query";
8
8
  import { FilterChipGroup, ListingLayout, RowActionMenu, useToast } from "../../../ui";
9
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
10
10
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
11
+ import { ADMIN_BULK_ACTIONS, ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
11
12
  import { ADMIN_STORE_STATUS_TABS } from "../constants/filter-tabs";
12
13
  import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
13
14
  import { DataListingView } from "./DataListingView";
@@ -68,20 +69,24 @@ export function AdminStoresView({ children, ...props }) {
68
69
  getTotal: (response, mappedRows) => typeof response.total === "number" ? response.total : mappedRows.length,
69
70
  buildFilters: (state) => state.status && state.status !== "All" ? sieveFilter("status", SIEVE_OP.EQ, state.status) : undefined,
70
71
  onRowClick: (row) => setEditorRow(row),
71
- buildBulkActions: (selection) => [
72
- {
73
- id: "manage",
74
- label: ACTIONS.ADMIN["manage-store"].label,
75
- variant: "primary",
76
- onClick: () => {
77
- const id = selection.selectedIds[0];
78
- const row = selection.rows.find((r) => r.id === id) ?? null;
79
- if (row)
80
- setEditorRow(row);
81
- selection.clearSelection();
82
- },
72
+ // Rule #7: bulk-action array sourced from the ADMIN_BULK_ACTIONS preset.
73
+ // Only MANAGE has a wired handler today (opens the editor for the first
74
+ // selected row); APPROVE/REJECT/SUSPEND/DELETE are left out until they
75
+ // have real bulk handlers.
76
+ buildBulkActions: (selection) => [ROW_ACTION_ID.MANAGE]
77
+ .filter((id) => ADMIN_BULK_ACTIONS.stores.includes(id))
78
+ .map((id) => ({
79
+ id,
80
+ label: ROW_ACTION_META[id].label,
81
+ variant: "primary",
82
+ onClick: () => {
83
+ const rowId = selection.selectedIds[0];
84
+ const row = selection.rows.find((r) => r.id === rowId) ?? null;
85
+ if (row)
86
+ setEditorRow(row);
87
+ selection.clearSelection();
83
88
  },
84
- ],
89
+ })),
85
90
  renderRowActions: (row) => {
86
91
  const isSuspended = row.status?.toLowerCase() === "suspended";
87
92
  const isVerified = Boolean(row._raw?.isVerified);
@@ -3,12 +3,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { Code, useApiMutation } from "@mohasinac/appkit/client";
4
4
  import React from "react";
5
5
  import { useQueryClient } from "@tanstack/react-query";
6
- import { Button, Div, FormActions, HorizontalRule, Input, Label, Row, Select, SideDrawer, Span, Stack, Text, Toggle, useToast } from "../../../ui";
6
+ import { Button, Div, FormActions, HorizontalRule, Input, Label, Row, Select, SideDrawer, Span, Stack, Text, Textarea, Toggle, useToast } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
- import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
+ import { ADMIN_ENDPOINTS, SUPPORT_ENDPOINTS } from "../../../constants/api-endpoints";
9
9
  const __P = {
10
- p3: "p-3",
11
- p4: "p-4",
10
+ p3: "p-[var(--appkit-space-3)]",
11
+ p4: "p-[var(--appkit-space-4)]",
12
12
  };
13
13
  const __O = {
14
14
  yAuto: "overflow-y-auto",
@@ -91,7 +91,7 @@ export function AdminSupportTicketDetailView({ open, onClose, ticketId, subject,
91
91
  });
92
92
  const replyMutation = useApiMutation({
93
93
  mutationFn: async () => {
94
- await apiClient.post(`/api/support/tickets/${ticketId}/messages`, { body: replyBody, newStatus: status });
94
+ await apiClient.post(SUPPORT_ENDPOINTS.TICKET_MESSAGES(ticketId), { body: replyBody, newStatus: status });
95
95
  },
96
96
  onSuccess: () => {
97
97
  showToast("Reply sent.", "success");
@@ -241,7 +241,7 @@ export function AdminSupportTicketDetailView({ open, onClose, ticketId, subject,
241
241
  showToast(err?.message ?? "Failed to update order items.", "error");
242
242
  },
243
243
  });
244
- return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: subject ?? "Support Ticket", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "md", children: [_jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-flex ${STATUS_COLOR[currentStatus ?? "open"] ?? STATUS_COLOR.open}`, rounded: "full", padding: "pill-sm-tall", children: (currentStatus ?? "open").replace(/_/g, " ") }), _jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: category }), orderId && (_jsxs(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: ["Order: ", orderId] }))] }), _jsxs(Div, { textSize: "sm", color: "muted", children: ["From: ", _jsx(Span, { weight: "medium", color: "primary", children: userDisplayName })] }), description && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [_jsx(Text, { className: "mb-1 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Description" }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", size: "sm", children: description })] })), messages.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsxs(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: ["Messages (", messages.length, ")"] }), _jsx(Stack, { className: `max-h-64 ${__O.yAuto}`, gap: "sm", children: messages.map((msg, i) => (_jsxs(Div, { textSize: "sm", surface: msg.authorRole === "user" ? "default" : "info-surface", className: msg.authorRole === "user" ? "border border-[var(--appkit-color-border)]" : "border border-[var(--appkit-color-info)]", rounded: "lg", padding: "sm", children: [_jsxs(Row, { color: "muted", textSize: "xs", className: "mb-1", align: "center", gap: "sm", children: [_jsx(Span, { weight: "medium", color: "muted", children: ROLE_LABEL[msg.authorRole ?? "user"] ?? msg.authorRole }), msg.createdAt && (_jsx(Span, { children: new Date(msg.createdAt).toLocaleString() }))] }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", children: msg.body })] }, msg.id ?? i))) })] })), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Reply to user" }), _jsx("textarea", { value: replyBody, onChange: (e) => setReplyBody(e.target.value), rows: 3, placeholder: "Type a reply\u2026", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: replyMutation.isPending, disabled: !replyBody.trim() || !ticketId || replyMutation.isPending, onClick: () => replyMutation.mutate(), children: "Send reply" })] }), _jsx(HorizontalRule, { tone: "subtle", spacing: "comfortable" }), _jsx(Select, { label: "Status", options: STATUS_OPTIONS, value: status, onValueChange: setStatus }), _jsx(Select, { label: "Priority", options: PRIORITY_OPTIONS, value: priority, onValueChange: setPriority }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Internal notes (staff only)" }), _jsx("textarea", { value: notes, onChange: (e) => setNotes(e.target.value), rows: 3, placeholder: "Notes visible only to admins and employees\u2026", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-zinc-400 focus:outline-none focus:ring-2 focus:ring-primary-500" })] }), _jsxs(Stack, { padding: "sm", gap: "sm", rounded: "lg", border: "default", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Linked parties" }), _jsx(Text, { size: "xs", color: "muted", children: "Tag the buyer / store / order / product / bid this ticket concerns." }), [
244
+ return (_jsx(SideDrawer, { isOpen: open, onClose: onClose, title: subject ?? "Support Ticket", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "md", children: [_jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [_jsx(Span, { size: "xs", weight: "medium", className: `inline-flex ${STATUS_COLOR[currentStatus ?? "open"] ?? STATUS_COLOR.open}`, rounded: "full", padding: "pill-sm-tall", children: (currentStatus ?? "open").replace(/_/g, " ") }), _jsx(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: category }), orderId && (_jsxs(Span, { size: "xs", rounded: "full", padding: "pill-sm-tall", surface: "subtle", color: "muted", children: ["Order: ", orderId] }))] }), _jsxs(Div, { textSize: "sm", color: "muted", children: ["From: ", _jsx(Span, { weight: "medium", color: "primary", children: userDisplayName })] }), description && (_jsxs(Div, { className: `${__P.p3}`, rounded: "lg", surface: "muted", border: "default", children: [_jsx(Text, { className: "mb-1 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Description" }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", size: "sm", children: description })] })), messages.length > 0 && (_jsxs(Stack, { gap: "sm", children: [_jsxs(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: ["Messages (", messages.length, ")"] }), _jsx(Stack, { className: `max-h-64 ${__O.yAuto}`, gap: "sm", children: messages.map((msg, i) => (_jsxs(Div, { textSize: "sm", surface: msg.authorRole === "user" ? "default" : "info-surface", className: msg.authorRole === "user" ? "border border-[var(--appkit-color-border)]" : "border border-[var(--appkit-color-info)]", rounded: "lg", padding: "sm", children: [_jsxs(Row, { color: "muted", textSize: "xs", className: "mb-1", align: "center", gap: "sm", children: [_jsx(Span, { weight: "medium", color: "muted", children: ROLE_LABEL[msg.authorRole ?? "user"] ?? msg.authorRole }), msg.createdAt && (_jsx(Span, { children: new Date(msg.createdAt).toLocaleString() }))] }), _jsx(Text, { className: "whitespace-pre-wrap", color: "primary", children: msg.body })] }, msg.id ?? i))) })] })), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Reply to user" }), _jsx(Textarea, { value: replyBody, onChange: (e) => setReplyBody(e.target.value), rows: 3, placeholder: "Type a reply\u2026" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: replyMutation.isPending, disabled: !replyBody.trim() || !ticketId || replyMutation.isPending, onClick: () => replyMutation.mutate(), children: "Send reply" })] }), _jsx(HorizontalRule, { tone: "subtle", spacing: "comfortable" }), _jsx(Select, { label: "Status", options: STATUS_OPTIONS, value: status, onValueChange: setStatus }), _jsx(Select, { label: "Priority", options: PRIORITY_OPTIONS, value: priority, onValueChange: setPriority }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { className: "uppercase tracking-wide", color: "muted", size: "xs", weight: "semibold", children: "Internal notes (staff only)" }), _jsx(Textarea, { value: notes, onChange: (e) => setNotes(e.target.value), rows: 3, placeholder: "Notes visible only to admins and employees\u2026" })] }), _jsxs(Stack, { padding: "sm", gap: "sm", rounded: "lg", border: "default", children: [_jsx(Text, { className: "tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Linked parties" }), _jsx(Text, { size: "xs", color: "muted", children: "Tag the buyer / store / order / product / bid this ticket concerns." }), [
245
245
  ["userId", "User slug"],
246
246
  ["storeId", "Store slug"],
247
247
  ["orderId", "Order ID"],
@@ -255,7 +255,7 @@ function OrderItemsPanel(props) {
255
255
  const q = Math.max(0, parseInt(raw, 10) || 0);
256
256
  setOrderItems((prev) => prev.map((p, i) => (i === idx ? { ...p, quantity: q } : p)));
257
257
  };
258
- return (_jsxs(Stack, { padding: "sm", className: "border border-info/40 bg-[var(--appkit-color-info-surface)]/40", gap: "sm", rounded: "lg", children: [_jsx(Text, { className: "text-info tracking-wide", size: "xs", weight: "semibold", transform: "uppercase", children: "Modify order items" }), linkedOrderId ? (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Editing order: ", _jsx(Code, { className: "font-mono", children: linkedOrderId })] }), !orderItemsOpen ? (_jsx(Button, { type: "button", variant: "secondary", size: "sm", isLoading: loadOrderItems.isPending, disabled: loadOrderItems.isPending, onClick: () => loadOrderItems.mutate(), children: "Load current items" })) : (_jsxs(_Fragment, { children: [orderItems.length === 0 ? (_jsx(Text, { size: "xs", color: "muted", children: "Order has no items." })) : (_jsx(Stack, { gap: "sm", children: orderItems.map((it, idx) => (_jsxs(Row, { paddingY: "y-2xs", padding: "x-xs", rounded: "default", align: "center", gap: "sm", border: "default", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", size: "xs", weight: "medium", children: it.productTitle }), _jsxs(Text, { size: "xs", color: "muted", children: [it.productId, " \u00B7 \u20B9", (it.unitPrice / 100).toFixed(2), "/ea"] })] }), _jsx("input", { type: "number", min: "0", value: it.quantity, onChange: (e) => updateQty(idx, e.target.value), className: "w-16 rounded border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-2 py-1 text-xs" })] }, `${it.productId}-${idx}`))) })), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setOrderItemsOpen(false), children: "Cancel" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: applyOrderItems.isPending, disabled: applyOrderItems.isPending, onClick: () => applyOrderItems.mutate(), children: "Apply changes" })] })] }))] })) : (_jsxs(Text, { size: "xs", color: "muted", children: ["Set the", " ", _jsx(Text, { as: "span", weight: "semibold", children: "Order ID" }), " ", "field in the Linked parties panel above to enable this action."] }))] }));
258
+ return (_jsxs(Stack, { padding: "sm", className: "border border-info/40 bg-[var(--appkit-color-info-surface)]/40", gap: "sm", rounded: "lg", children: [_jsx(Text, { className: "text-info tracking-wide", size: "xs", weight: "semibold", transform: "uppercase", children: "Modify order items" }), linkedOrderId ? (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "xs", color: "muted", children: ["Editing order: ", _jsx(Code, { className: "font-mono", children: linkedOrderId })] }), !orderItemsOpen ? (_jsx(Button, { type: "button", variant: "secondary", size: "sm", isLoading: loadOrderItems.isPending, disabled: loadOrderItems.isPending, onClick: () => loadOrderItems.mutate(), children: "Load current items" })) : (_jsxs(_Fragment, { children: [orderItems.length === 0 ? (_jsx(Text, { size: "xs", color: "muted", children: "Order has no items." })) : (_jsx(Stack, { gap: "sm", children: orderItems.map((it, idx) => (_jsxs(Row, { paddingY: "y-2xs", padding: "x-xs", rounded: "default", align: "center", gap: "sm", border: "default", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "truncate", size: "xs", weight: "medium", children: it.productTitle }), _jsxs(Text, { size: "xs", color: "muted", children: [it.productId, " \u00B7 \u20B9", (it.unitPrice / 100).toFixed(2), "/ea"] })] }), _jsx(Input, { bare: true, type: "number", min: "0", value: it.quantity, onChange: (e) => updateQty(idx, e.target.value), className: "w-16 rounded border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)]" })] }, `${it.productId}-${idx}`))) })), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => setOrderItemsOpen(false), children: "Cancel" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", isLoading: applyOrderItems.isPending, disabled: applyOrderItems.isPending, onClick: () => applyOrderItems.mutate(), children: "Apply changes" })] })] }))] })) : (_jsxs(Text, { size: "xs", color: "muted", children: ["Set the", " ", _jsx(Text, { as: "span", weight: "semibold", children: "Order ID" }), " ", "field in the Linked parties panel above to enable this action."] }))] }));
259
259
  }
260
260
  function StoreChangePanel(props) {
261
261
  const { linkedStoreId, storeStatus, setStoreStatus, storeIsVerified, setStoreIsVerified, storeIsFeatured, setStoreIsFeatured, applyStoreChange, } = props;
@@ -7,7 +7,7 @@ import { UserPlus } from "lucide-react";
7
7
  import { Button, FilterChipGroup, ListingLayout, RowActionMenu } from "../../../ui";
8
8
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
9
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
10
- import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
10
+ import { ADMIN_BULK_ACTIONS, ROW_ACTION_META } from "../../products/constants/action-defs";
11
11
  import { ALL_TAB } from "../constants/filter-tabs";
12
12
  import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
13
13
  import { DataListingView } from "./DataListingView";
@@ -94,13 +94,17 @@ export function AdminTeamView({ children, onBulkRemove, ...props }) {
94
94
  },
95
95
  buildFilters: (state) => state.group && state.group !== "All" ? sieveFilter("permissionGroup", SIEVE_OP.EQ, state.group) : undefined,
96
96
  toolbarExtra: (_jsxs(Button, { gap: "sm", type: "button", variant: "primary", onClick: openInvite, className: "whitespace-nowrap", children: [_jsx(UserPlus, { className: "h-4 w-4" }), "Invite Employee"] })),
97
+ // Rule #7: bulk-action array sourced from the ADMIN_BULK_ACTIONS preset.
97
98
  buildBulkActions: onBulkRemove
98
- ? (selection) => [
99
- buildBulkAction(ACTIONS.ADMIN["remove-team-member"], async () => {
99
+ ? (selection) => ADMIN_BULK_ACTIONS.team.map((id) => ({
100
+ id,
101
+ label: ROW_ACTION_META[id].label,
102
+ destructive: ROW_ACTION_META[id].destructive,
103
+ onClick: async () => {
100
104
  await onBulkRemove(selection.selectedIds);
101
105
  selection.clearSelection();
102
- }),
103
- ]
106
+ },
107
+ }))
104
108
  : undefined,
105
109
  renderRowActions: (row) => (_jsx(RowActionMenu, { actions: [
106
110
  {
@@ -8,6 +8,7 @@ import { useQueryClient } from "@tanstack/react-query";
8
8
  import { Button, FilterChipGroup, Form, FormActions, Input, ListingLayout, Modal, RowActionMenu, Text as AppText, useToast, } from "../../../ui";
9
9
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
10
10
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
11
+ import { ADMIN_BULK_ACTIONS, ROW_ACTION_META, ROW_ACTION_ID } from "../../products/constants/action-defs";
11
12
  import { ADMIN_USER_STATUS_TABS, ADMIN_USER_ROLE_TABS } from "../constants/filter-tabs";
12
13
  import { toRecordArray, toRelativeDate, toStringValue, } from "../hooks/useAdminListingData";
13
14
  import { DataListingView } from "./DataListingView";
@@ -108,22 +109,25 @@ export function AdminUsersView({ children, ...props }) {
108
109
  setSelectedRow(row);
109
110
  setDrawerOpen(true);
110
111
  },
111
- buildBulkActions: (selection) => [
112
- {
113
- id: "manage",
114
- label: ACTIONS.ADMIN["manage-user"].label,
115
- variant: "primary",
116
- onClick: () => {
117
- const id = selection.selectedIds[0];
118
- const row = selection.rows.find((r) => r.id === id) ?? null;
119
- if (row) {
120
- setSelectedRow(row);
121
- setDrawerOpen(true);
122
- }
123
- selection.clearSelection();
124
- },
112
+ // Rule #7: bulk-action array sourced from the ADMIN_BULK_ACTIONS preset.
113
+ // Only MANAGE has a wired handler today; SUSPEND/RESTORE/DELETE are left
114
+ // out until they have real bulk handlers.
115
+ buildBulkActions: (selection) => [ROW_ACTION_ID.MANAGE]
116
+ .filter((id) => ADMIN_BULK_ACTIONS.users.includes(id))
117
+ .map((id) => ({
118
+ id,
119
+ label: ROW_ACTION_META[id].label,
120
+ variant: "primary",
121
+ onClick: () => {
122
+ const rowId = selection.selectedIds[0];
123
+ const row = selection.rows.find((r) => r.id === rowId) ?? null;
124
+ if (row) {
125
+ setSelectedRow(row);
126
+ setDrawerOpen(true);
127
+ }
128
+ selection.clearSelection();
125
129
  },
126
- ],
130
+ })),
127
131
  renderRowActions: (row) => {
128
132
  const isBanned = row.status === "Hard banned";
129
133
  return (_jsx(RowActionMenu, { actions: [
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Div, Grid, Row, Span, Stack, Text } from "../../../ui";
3
+ import { Checkbox, Div, Grid, Row, Span, Stack, Text } from "../../../ui";
4
4
  const __P = {
5
- p3: "p-3",
5
+ p3: "p-[var(--appkit-space-3)]",
6
6
  };
7
7
  const __O = {
8
8
  hidden: "overflow-hidden",
@@ -31,16 +31,16 @@ function AdminCardItem({ row, view, selected, onToggleSelect, onRowClick, }) {
31
31
  };
32
32
  if (view === "list") {
33
33
  return (_jsxs(Row, { gap: "sm", className: [
34
- "px-4 py-3 cursor-pointer transition-colors hover:bg-zinc-50 hover:bg-[var(--appkit-color-surface-elevated)]/50",
34
+ "px-[var(--appkit-space-4)] py-[var(--appkit-space-3)] cursor-pointer transition-colors hover:bg-zinc-50 hover:bg-[var(--appkit-color-surface-elevated)]/50",
35
35
  selected ? "bg-primary-50/40 dark:bg-primary-900/10" : "",
36
- ].filter(Boolean).join(" "), onClick: handleClick, role: onRowClick ? "button" : undefined, children: [onToggleSelect && (_jsx(Div, { "data-checkbox": true, className: "shrink-0", onClick: (e) => { e.stopPropagation(); onToggleSelect(row.id); }, children: _jsx("input", { type: "checkbox", checked: selected, onChange: () => onToggleSelect(row.id), className: "h-4 w-4 rounded border-zinc-300 text-primary accent-primary cursor-pointer", "aria-label": `Select ${row.primary}` }) })), _jsxs(Stack, { gap: "none", className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "truncate", color: "primary", children: row.primary }), _jsx(Text, { size: "xs", color: "muted", className: "truncate", children: row.secondary })] }), flags.length > 0 && (_jsx(Row, { gap: "xs", className: "hidden sm:flex shrink-0", children: flags.map(({ key, label, color }) => (_jsx(Span, { padding: "pill-2xs", weight: "medium", className: `inline-flex text-[10px] ${color}`, rounded: "full", children: label }, key))) })), _jsx(StatusBadge, { status: row.status }), _jsx(Span, { size: "xs", color: "muted", className: "hidden sm:block shrink-0 w-24", align: "end", children: row.updatedAt })] }));
36
+ ].filter(Boolean).join(" "), onClick: handleClick, role: onRowClick ? "button" : undefined, children: [onToggleSelect && (_jsx(Div, { "data-checkbox": true, className: "shrink-0", onClick: (e) => { e.stopPropagation(); onToggleSelect(row.id); }, children: _jsx(Checkbox, { bare: true, checked: selected, onChange: () => onToggleSelect(row.id), className: "h-4 w-4 rounded border-zinc-300 text-primary accent-primary cursor-pointer", "aria-label": `Select ${row.primary}` }) })), _jsxs(Stack, { gap: "none", className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "truncate", color: "primary", children: row.primary }), _jsx(Text, { size: "xs", color: "muted", className: "truncate", children: row.secondary })] }), flags.length > 0 && (_jsx(Row, { gap: "xs", className: "hidden sm:flex shrink-0", children: flags.map(({ key, label, color }) => (_jsx(Span, { padding: "pill-2xs", weight: "medium", className: `inline-flex text-[10px] ${color}`, rounded: "full", children: label }, key))) })), _jsx(StatusBadge, { status: row.status }), _jsx(Span, { size: "xs", color: "muted", className: "hidden sm:block shrink-0 w-24", align: "end", children: row.updatedAt })] }));
37
37
  }
38
38
  return (_jsxs(Div, { rounded: "xl", className: [
39
39
  "border overflow-hidden cursor-pointer transition-all hover:shadow-md hover:-translate-y-0.5",
40
40
  selected
41
41
  ? "border-primary ring-1 ring-primary/20 bg-primary-50/30 dark:bg-primary-900/10"
42
42
  : "border-zinc-100 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]",
43
- ].filter(Boolean).join(" "), onClick: handleClick, role: onRowClick ? "button" : undefined, children: [onToggleSelect && (_jsxs(Row, { gap: "xs", "data-checkbox": true, paddingY: "t-sm", padding: "x-sm", onClick: (e) => { e.stopPropagation(); onToggleSelect(row.id); }, children: [_jsx("input", { type: "checkbox", checked: selected, onChange: () => onToggleSelect(row.id), className: "h-4 w-4 rounded border-zinc-300 text-primary accent-primary cursor-pointer", "aria-label": `Select ${row.primary}` }), flags.length > 0 && (_jsx(Row, { gap: "xs", wrap: true, children: flags.map(({ key, label, color }) => (_jsx(Span, { padding: "pill-2xs", weight: "medium", className: `inline-flex text-[10px] ${color}`, rounded: "full", children: label }, key))) }))] })), _jsxs(Stack, { gap: "xs", className: `${__P.p3}.5`, children: [_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "line-clamp-2 leading-snug", color: "primary", children: row.primary }), _jsx(Text, { size: "xs", color: "muted", className: "truncate", children: row.secondary })] }), _jsxs(Row, { justify: "between", gap: "xs", children: [_jsx(StatusBadge, { status: row.status }), _jsx(Span, { color: "muted", className: "text-[11px] shrink-0", children: row.updatedAt })] })] })] }));
43
+ ].filter(Boolean).join(" "), onClick: handleClick, role: onRowClick ? "button" : undefined, children: [onToggleSelect && (_jsxs(Row, { gap: "xs", "data-checkbox": true, paddingY: "t-sm", padding: "x-sm", onClick: (e) => { e.stopPropagation(); onToggleSelect(row.id); }, children: [_jsx(Checkbox, { bare: true, checked: selected, onChange: () => onToggleSelect(row.id), className: "h-4 w-4 rounded border-zinc-300 text-primary accent-primary cursor-pointer", "aria-label": `Select ${row.primary}` }), flags.length > 0 && (_jsx(Row, { gap: "xs", wrap: true, children: flags.map(({ key, label, color }) => (_jsx(Span, { padding: "pill-2xs", weight: "medium", className: `inline-flex text-[10px] ${color}`, rounded: "full", children: label }, key))) }))] })), _jsxs(Stack, { gap: "xs", className: `${__P.p3}.5`, children: [_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "line-clamp-2 leading-snug", color: "primary", children: row.primary }), _jsx(Text, { size: "xs", color: "muted", className: "truncate", children: row.secondary })] }), _jsxs(Row, { justify: "between", gap: "xs", children: [_jsx(StatusBadge, { status: row.status }), _jsx(Span, { color: "muted", className: "text-[11px] shrink-0", children: row.updatedAt })] })] })] }));
44
44
  }
45
45
  export function AdminViewCards({ rows, view, isLoading, emptyLabel = "No items found", onRowClick, selectedIdSet, onToggleSelect, }) {
46
46
  if (isLoading) {
@@ -6,7 +6,7 @@ import { DynamicBgDiv } from "../../../ui/components/DynamicBgDiv";
6
6
  import { formatCurrency } from "../../../utils/number.formatter";
7
7
  import { getDefaultCurrency } from "../../../core/baseline-resolver";
8
8
  const __P = {
9
- p5: "p-5",
9
+ p5: "p-[var(--appkit-space-5)]",
10
10
  };
11
11
  const __O = {
12
12
  hidden: "overflow-hidden",
@@ -12,7 +12,7 @@ export function DataListingView({ config, }) {
12
12
  ...config,
13
13
  initialView: effectiveInitialView,
14
14
  });
15
- const { view, setView, table, panel, searchInput, setSearchInput, commitSearch, filterOpen, setFilterOpen, openFilters, applyFilters, clearFilters, pendingFilters, setPendingFilters, activeFilterCount, hasActiveState, resetAll, rows, isLoading, errorMessage, currentPage, totalPages, selection, } = listing;
15
+ const { view, setView, table, panel, searchInput, setSearchInput, commitSearch, filterOpen, setFilterOpen, openFilters, applyFilters, clearFilters, pendingFilters, setPendingFilters, activeFilterCount, hasActiveState, resetAll, rows, isLoading, errorMessage, currentPage, totalPages, selection, pageSize, setPageSize, } = listing;
16
16
  const selectionContext = {
17
17
  selectedIds: selection.selectedIds,
18
18
  selectedCount: selection.selectedCount,
@@ -44,7 +44,7 @@ export function DataListingView({ config, }) {
44
44
  const isEditorOpen = panel.isCreateOpen || panel.isEditOpen;
45
45
  return (_jsxs(Div, { className: config.className ?? "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: config.searchPlaceholder, onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || config.defaultSort, sortOptions: config.sortOptions, onSortChange: (v) => table.set("sort", v), showTableView: !config.hideTableView, toggles: config.toggles, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, extra: config.primaryAction || config.toolbarExtra ? (_jsxs(Row, { align: "center", gap: "sm", children: [config.toolbarExtra, config.primaryAction && (_jsxs(Button, { gap: "sm", size: "sm", onClick: () => config.primaryAction.onClick({
46
46
  openCreatePanel: panel.openCreatePanel,
47
- }), children: [config.primaryAction.icon ?? _jsx(Plus, { className: "h-4 w-4" }), config.primaryAction.label] }))] })) : undefined }), config.renderAboveContent?.(), bulkActionItems && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActionItems })), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), view === "table" ? (_jsx(DataTable, { columns: config.columns, rows: rows, isLoading: isLoading, emptyLabel: config.emptyLabel ?? `No ${config.title.toLowerCase()} found`, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next
47
+ }), children: [config.primaryAction.icon ?? _jsx(Plus, { className: "h-4 w-4" }), config.primaryAction.label] }))] })) : undefined }), config.renderAboveContent?.(), bulkActionItems && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActionItems })), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p), pageSize: pageSize, onPageSizeChange: setPageSize, paginationConfig: { showPageSizeSelector: true, pageSizeOptions: [10, 25, 50, 100] } }) })), _jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), view === "table" ? (_jsx(DataTable, { columns: config.columns, rows: rows, isLoading: isLoading, emptyLabel: config.emptyLabel ?? `No ${config.title.toLowerCase()} found`, selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: (next) => next
48
48
  ? selection.setSelectedIds(rows.map((r) => r.id))
49
49
  : selection.clearSelection(), getRowHref: config.getRowHref, onRowClick: config.onRowClick
50
50
  ? (row) => config.onRowClick(row, {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { BaseListingCard, Button, Div, Row, Span, Stack, Table, Tbody, Td, Text, Th, Thead, Tr } from "../../../ui";
3
+ import { BaseListingCard, Button, Checkbox, Div, Row, Span, Stack, Table, Tbody, Td, Text, Th, Thead, Tr } from "../../../ui";
4
4
  import { useLongPress } from "../../../react/hooks/useLongPress";
5
5
  const __O = {
6
6
  hidden: "overflow-hidden",
@@ -47,5 +47,5 @@ export function DataTable({ columns: columnsProp, rows, isLoading, sortKey, sort
47
47
  const columns = (columnsProp ?? DEFAULT_COLUMNS);
48
48
  const selectionEnabled = Boolean(onToggleSelect);
49
49
  const allRowsSelected = selectionEnabled && rows.length > 0 && rows.every((r) => selectedIds?.has(r.id));
50
- return (_jsxs(Div, { surface: "card", className: `${__O.hidden}`, children: [_jsx(Div, { className: `${__O.xAuto}`, children: _jsxs(Table, { "data-testid": "data-table", size: "sm", children: [_jsx(Thead, { children: _jsxs(Tr, { className: "bg-[var(--appkit-color-bg)] dark:bg-[var(--appkit-color-surface-elevated)]", border: "default", children: [selectionEnabled && (_jsx(Th, { padding: "xs-3", scope: "col", className: "w-10", children: onToggleSelectAll && (_jsx("input", { type: "checkbox", "data-testid": "select-all-checkbox", "aria-label": allRowsSelected ? "Deselect all" : "Select all", checked: allRowsSelected, onChange: () => onToggleSelectAll(!allRowsSelected), className: "h-4 w-4 rounded border-[var(--appkit-color-border)] accent-zinc-900 dark:accent-zinc-100" })) })), columns.map((col) => (_jsxs(Th, { scope: "col", onClick: col.sortable && onSort ? () => onSort(col.key) : undefined, className: `text-left text-[var(--appkit-color-text)] text-[var(--appkit-color-text)] ${col.sortable && onSort ? "cursor-pointer select-none hover:text-primary" : ""} ${col.className ?? ""}`, padding: "md", weight: "semibold", children: [col.header, col.sortable && sortKey === col.key && (_jsx(Span, { className: "ml-1", children: sortDir === "asc" ? "↑" : "↓" }))] }, col.key))), renderRowActions && _jsx(Th, { padding: "xs-3", scope: "col", className: "w-12" })] }) }), _jsx(Tbody, { children: isLoading ? (Array.from({ length: 5 }).map((_, i) => (_jsxs(Tr, { border: "default", children: [selectionEnabled && _jsx(Td, { padding: "xs-3", className: "w-10" }), columns.map((col) => (_jsx(Td, { padding: "md", children: _jsx(Div, { className: "h-4 w-full animate-pulse bg-neutral-200", rounded: "default" }) }, col.key)))] }, i)))) : rows.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: columns.length + (selectionEnabled ? 1 : 0) + (renderRowActions ? 1 : 0), align: "center", color: "faint", paddingX: "md", paddingY: "md", children: emptyLabel }) })) : (rows.map((row) => (_jsx(SelectableRow, { row: row, columns: columns, isSelected: selectedIds?.has(row.id) ?? false, onToggle: onToggleSelect, renderRowActions: renderRowActions, onRowClick: onRowClick, rowHref: getRowHref?.(row), selectionEnabled: selectionEnabled }, row.id)))) })] }) }), totalPages > 1 && onPageChange && (_jsx(Row, { className: "border-t border-neutral-200", padding: "inline", align: "center", justify: "end", gap: "sm", children: Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => (_jsx(Button, { onClick: () => onPageChange(p), variant: p === currentPage ? "primary" : "ghost", size: "sm", className: `h-8 w-8 rounded text-xs font-medium transition ${p === currentPage ? "bg-neutral-900 text-white" : "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)]"}`, children: p }, p))) }))] }));
50
+ return (_jsxs(Div, { surface: "card", className: `${__O.hidden}`, children: [_jsx(Div, { className: `${__O.xAuto}`, children: _jsxs(Table, { "data-testid": "data-table", size: "sm", children: [_jsx(Thead, { children: _jsxs(Tr, { className: "bg-[var(--appkit-color-bg)] dark:bg-[var(--appkit-color-surface-elevated)]", border: "default", children: [selectionEnabled && (_jsx(Th, { padding: "xs-3", scope: "col", className: "w-10", children: onToggleSelectAll && (_jsx(Checkbox, { bare: true, "data-testid": "select-all-checkbox", "aria-label": allRowsSelected ? "Deselect all" : "Select all", checked: allRowsSelected, onChange: () => onToggleSelectAll(!allRowsSelected), className: "h-4 w-4 rounded border-[var(--appkit-color-border)] accent-zinc-900 dark:accent-zinc-100" })) })), columns.map((col) => (_jsxs(Th, { scope: "col", onClick: col.sortable && onSort ? () => onSort(col.key) : undefined, className: `text-left text-[var(--appkit-color-text)] text-[var(--appkit-color-text)] ${col.sortable && onSort ? "cursor-pointer select-none hover:text-primary" : ""} ${col.className ?? ""}`, padding: "md", weight: "semibold", children: [col.header, col.sortable && sortKey === col.key && (_jsx(Span, { className: "ml-1", children: sortDir === "asc" ? "↑" : "↓" }))] }, col.key))), renderRowActions && _jsx(Th, { padding: "xs-3", scope: "col", className: "w-12" })] }) }), _jsx(Tbody, { children: isLoading ? (Array.from({ length: 5 }).map((_, i) => (_jsxs(Tr, { border: "default", children: [selectionEnabled && _jsx(Td, { padding: "xs-3", className: "w-10" }), columns.map((col) => (_jsx(Td, { padding: "md", children: _jsx(Div, { className: "h-4 w-full animate-pulse bg-neutral-200", rounded: "default" }) }, col.key)))] }, i)))) : rows.length === 0 ? (_jsx(Tr, { children: _jsx(Td, { colSpan: columns.length + (selectionEnabled ? 1 : 0) + (renderRowActions ? 1 : 0), align: "center", color: "faint", paddingX: "md", paddingY: "md", children: emptyLabel }) })) : (rows.map((row) => (_jsx(SelectableRow, { row: row, columns: columns, isSelected: selectedIds?.has(row.id) ?? false, onToggle: onToggleSelect, renderRowActions: renderRowActions, onRowClick: onRowClick, rowHref: getRowHref?.(row), selectionEnabled: selectionEnabled }, row.id)))) })] }) }), totalPages > 1 && onPageChange && (_jsx(Row, { className: "border-t border-neutral-200", padding: "inline", align: "center", justify: "end", gap: "sm", children: Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => (_jsx(Button, { onClick: () => onPageChange(p), variant: p === currentPage ? "primary" : "ghost", size: "sm", className: `h-8 w-8 rounded text-[length:var(--appkit-text-xs)] font-medium transition ${p === currentPage ? "bg-neutral-900 text-white" : "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)]"}`, children: p }, p))) }))] }));
51
51
  }
@@ -9,5 +9,5 @@ const DEFAULT_LABELS = {
9
9
  };
10
10
  export function DrawerFormFooter({ onCancel, onSubmit, onDelete, isLoading = false, isSubmitDisabled = false, className = "", labels, variant = "footer", themeConfig = { borderClass: "border-t border-[var(--appkit-color-border)]" }, }) {
11
11
  const l = { ...DEFAULT_LABELS, ...labels };
12
- return (_jsxs(Div, { className: `flex items-center gap-3${variant === "inline" ? ` pt-4 ${themeConfig.borderClass}` : ""} ${className}`, children: [onDelete && (_jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.DELETE].variant, onClick: onDelete, disabled: isLoading, size: "md", children: l.delete })), _jsxs(Row, { className: `${!onDelete ? " ml-auto" : ""}`, align: "center", gap: "3", children: [_jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.CANCEL].variant, onClick: onCancel, disabled: isLoading, size: "md", children: l.cancel }), _jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.SUBMIT].variant, onClick: onSubmit, disabled: isLoading || isSubmitDisabled, size: "md", children: isLoading ? l.saving : l.submit })] })] }));
12
+ return (_jsxs(Div, { className: `flex items-center gap-[var(--appkit-space-3)]${variant === "inline" ? ` pt-[var(--appkit-space-4)] ${themeConfig.borderClass}` : ""} ${className}`, children: [onDelete && (_jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.DELETE].variant, onClick: onDelete, disabled: isLoading, size: "md", children: l.delete })), _jsxs(Row, { className: `${!onDelete ? " ml-auto" : ""}`, align: "center", gap: "3", children: [_jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.CANCEL].variant, onClick: onCancel, disabled: isLoading, size: "md", children: l.cancel }), _jsx(Button, { variant: FORM_ACTION_META[FORM_ACTION_ID.SUBMIT].variant, onClick: onSubmit, disabled: isLoading || isSubmitDisabled, size: "md", children: isLoading ? l.saving : l.submit })] })] }));
13
13
  }
@@ -3,8 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import dynamic from "next/dynamic";
4
4
  import { Div, Heading } from "../../../../ui";
5
5
  const __P = {
6
- p4: "p-4",
7
- p6: "p-6",
6
+ p4: "p-[var(--appkit-space-4)]",
7
+ p6: "p-[var(--appkit-space-6)]",
8
8
  };
9
9
  // recharts exports generic components (<DataPointType>) that don't satisfy
10
10
  // next/dynamic's ComponentType<P> constraint — cast each to ComponentType<any>.
@@ -13,5 +13,5 @@ const GRADIENTS = {
13
13
  };
14
14
  export function AdminStatCard({ label, value, sub, icon, gradient = "brand", className = "", }) {
15
15
  const resolvedGradient = GRADIENTS[gradient] ?? gradient;
16
- return (_jsxs(Div, { className: `relative border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden ${className}`, rounded: "xl", shadow: "sm-hover-md", children: [_jsx(DynamicBgDiv, { background: resolvedGradient, className: "absolute top-0 left-0 right-0 h-[3px]", "aria-hidden": "true" }), _jsxs(Row, { paddingX: "x-5", paddingY: "b-md-lg", padding: "t-lg", align: "start", justify: "between", gap: "3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx(Text, { className: "text-[11px] tracking-widest text-[var(--appkit-color-text-muted)]", weight: "semibold", transform: "uppercase", children: label }), _jsx(Heading, { level: 3, className: "mt-2 tabular-nums leading-none text-[var(--appkit-color-text)]", size: "2xl", weight: "bold", children: value }), sub && (_jsx(Text, { className: "mt-1.5 text-[var(--appkit-color-text-muted)]", size: "xs", children: sub }))] }), icon && (_jsx(DynamicBgDiv, { background: resolvedGradient, className: "flex-shrink-0 w-10 h-10 flex items-center justify-center rounded-lg text-xl", children: icon }))] })] }));
16
+ return (_jsxs(Div, { className: `relative border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden ${className}`, rounded: "xl", shadow: "sm-hover-md", children: [_jsx(DynamicBgDiv, { background: resolvedGradient, className: "absolute top-0 left-0 right-0 h-[3px]", "aria-hidden": "true" }), _jsxs(Row, { paddingX: "x-5", paddingY: "b-md-lg", padding: "t-lg", align: "start", justify: "between", gap: "3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx(Text, { className: "text-[11px] tracking-widest text-[var(--appkit-color-text-muted)]", weight: "semibold", transform: "uppercase", children: label }), _jsx(Heading, { level: 3, className: "mt-2 tabular-nums leading-none text-[var(--appkit-color-text)]", size: "2xl", weight: "bold", children: value }), sub && (_jsx(Text, { className: "mt-1.5 text-[var(--appkit-color-text-muted)]", size: "xs", children: sub }))] }), icon && (_jsx(DynamicBgDiv, { background: resolvedGradient, className: "flex-shrink-0 w-10 h-10 flex items-center justify-center rounded-lg text-[length:var(--appkit-text-xl)]", children: icon }))] })] }));
17
17
  }