@mohasinac/appkit 2.3.1 → 2.3.2

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 (253) hide show
  1. package/dist/client.d.ts +12 -8
  2. package/dist/client.js +7 -4
  3. package/dist/constants/api-endpoints.d.ts +4 -0
  4. package/dist/constants/api-endpoints.js +2 -0
  5. package/dist/core/contact-submissions.repository.d.ts +32 -0
  6. package/dist/core/contact-submissions.repository.js +49 -0
  7. package/dist/core/index.d.ts +2 -0
  8. package/dist/core/index.js +1 -0
  9. package/dist/features/about/components/HowPayoutsWorkView.js +1 -1
  10. package/dist/features/account/components/AddressFilters.d.ts +5 -0
  11. package/dist/features/account/components/AddressFilters.js +20 -0
  12. package/dist/features/account/components/AddressesIndexListing.d.ts +6 -0
  13. package/dist/features/account/components/AddressesIndexListing.js +51 -0
  14. package/dist/features/account/components/UserSidebar.d.ts +7 -3
  15. package/dist/features/account/components/UserSidebar.js +55 -7
  16. package/dist/features/account/hooks/useAddresses.d.ts +7 -0
  17. package/dist/features/account/hooks/useAddresses.js +12 -1
  18. package/dist/features/admin/actions/admin-read-actions.d.ts +12 -0
  19. package/dist/features/admin/actions/admin-read-actions.js +18 -0
  20. package/dist/features/admin/components/AdminBlogView.js +26 -2
  21. package/dist/features/admin/components/AdminCarouselView.js +18 -2
  22. package/dist/features/admin/components/AdminCategoriesView.js +27 -2
  23. package/dist/features/admin/components/AdminContactView.d.ts +4 -0
  24. package/dist/features/admin/components/AdminContactView.js +50 -0
  25. package/dist/features/admin/components/AdminFaqsView.js +19 -2
  26. package/dist/features/admin/components/AdminListingScaffold.d.ts +11 -2
  27. package/dist/features/admin/components/AdminListingScaffold.js +14 -3
  28. package/dist/features/admin/components/AdminNewsletterView.d.ts +4 -0
  29. package/dist/features/admin/components/AdminNewsletterView.js +50 -0
  30. package/dist/features/admin/components/AdminProductsView.js +30 -2
  31. package/dist/features/admin/components/AdminReviewsView.js +26 -2
  32. package/dist/features/admin/components/AdminStoresView.js +17 -2
  33. package/dist/features/admin/components/AdminUsersView.js +27 -2
  34. package/dist/features/admin/components/DataTable.d.ts +2 -1
  35. package/dist/features/admin/components/DataTable.js +18 -4
  36. package/dist/features/admin/components/index.d.ts +6 -0
  37. package/dist/features/admin/components/index.js +3 -0
  38. package/dist/features/admin/hooks/useAdminListingData.d.ts +3 -1
  39. package/dist/features/admin/hooks/useAdminListingData.js +12 -7
  40. package/dist/features/admin/server.d.ts +3 -0
  41. package/dist/features/admin/server.js +2 -0
  42. package/dist/features/auctions/components/AuctionDetailPageView.js +93 -47
  43. package/dist/features/auctions/components/AuctionFilters.d.ts +8 -0
  44. package/dist/features/auctions/components/AuctionFilters.js +12 -0
  45. package/dist/features/auctions/components/AuctionsListView.d.ts +6 -1
  46. package/dist/features/auctions/components/AuctionsListView.js +37 -5
  47. package/dist/features/auctions/schemas/index.d.ts +4 -4
  48. package/dist/features/blog/components/BlogFeaturedCard.d.ts +1 -7
  49. package/dist/features/blog/components/BlogFeaturedCard.js +4 -5
  50. package/dist/features/blog/components/BlogFilters.js +2 -1
  51. package/dist/features/blog/components/BlogIndexListing.js +14 -9
  52. package/dist/features/blog/components/BlogIndexPageView.d.ts +6 -1
  53. package/dist/features/blog/components/BlogIndexPageView.js +10 -2
  54. package/dist/features/blog/components/BlogListView.d.ts +2 -1
  55. package/dist/features/blog/components/BlogListView.js +10 -3
  56. package/dist/features/categories/components/CategoriesIndexListing.d.ts +1 -1
  57. package/dist/features/categories/components/CategoriesIndexListing.js +41 -38
  58. package/dist/features/categories/components/CategoriesIndexPageView.d.ts +6 -1
  59. package/dist/features/categories/components/CategoriesIndexPageView.js +41 -2
  60. package/dist/features/categories/components/CategoryDetailPageView.js +13 -6
  61. package/dist/features/categories/components/CategoryDetailTabs.d.ts +5 -0
  62. package/dist/features/categories/components/CategoryDetailTabs.js +17 -0
  63. package/dist/features/categories/components/CategoryFilters.js +2 -1
  64. package/dist/features/categories/components/CategoryGrid.d.ts +2 -1
  65. package/dist/features/categories/components/CategoryGrid.js +8 -6
  66. package/dist/features/categories/components/CategoryProductsListing.js +22 -11
  67. package/dist/features/categories/components/index.d.ts +2 -0
  68. package/dist/features/categories/components/index.js +1 -0
  69. package/dist/features/categories/hooks/useCategories.d.ts +20 -0
  70. package/dist/features/categories/hooks/useCategories.js +50 -1
  71. package/dist/features/categories/hooks/useCategoryTree.d.ts +17 -0
  72. package/dist/features/categories/hooks/useCategoryTree.js +65 -0
  73. package/dist/features/events/components/AdminEventEditorView.d.ts +6 -0
  74. package/dist/features/events/components/AdminEventEditorView.js +203 -0
  75. package/dist/features/events/components/AdminEventsView.js +28 -2
  76. package/dist/features/events/components/EventCard.js +4 -2
  77. package/dist/features/events/components/EventFilters.js +2 -1
  78. package/dist/features/events/components/EventsIndexListing.js +40 -10
  79. package/dist/features/events/components/EventsListPageView.d.ts +6 -1
  80. package/dist/features/events/components/EventsListPageView.js +40 -7
  81. package/dist/features/events/components/index.d.ts +2 -0
  82. package/dist/features/events/components/index.js +1 -0
  83. package/dist/features/events/hooks/useEvents.js +2 -0
  84. package/dist/features/events/types/index.d.ts +1 -0
  85. package/dist/features/homepage/components/BlogArticlesSection.js +1 -1
  86. package/dist/features/homepage/components/EventsSection.js +1 -1
  87. package/dist/features/homepage/components/FeaturedAuctionsSection.js +1 -1
  88. package/dist/features/homepage/components/FeaturedPreOrdersSection.js +1 -1
  89. package/dist/features/homepage/components/FeaturedProductsSection.js +1 -1
  90. package/dist/features/homepage/components/FeaturedStoresSection.js +1 -1
  91. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  92. package/dist/features/homepage/components/MarketplaceHomepageView.js +27 -17
  93. package/dist/features/homepage/components/SectionCarousel.js +4 -4
  94. package/dist/features/homepage/components/ShopByCategorySection.js +2 -2
  95. package/dist/features/homepage/schemas/firestore.d.ts +1 -1
  96. package/dist/features/homepage/schemas/firestore.js +2 -1
  97. package/dist/features/layout/AppLayoutShell.d.ts +6 -2
  98. package/dist/features/layout/AppLayoutShell.js +7 -3
  99. package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +3 -1
  100. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +6 -2
  101. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +80 -12
  102. package/dist/features/pre-orders/components/PreOrderFilters.d.ts +8 -0
  103. package/dist/features/pre-orders/components/PreOrderFilters.js +21 -0
  104. package/dist/features/pre-orders/components/PreOrdersIndexListing.d.ts +2 -1
  105. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +69 -10
  106. package/dist/features/pre-orders/components/PreOrdersListView.d.ts +6 -1
  107. package/dist/features/pre-orders/components/PreOrdersListView.js +26 -7
  108. package/dist/features/pre-orders/components/index.d.ts +2 -0
  109. package/dist/features/pre-orders/components/index.js +1 -0
  110. package/dist/features/products/components/AuctionsIndexListing.d.ts +2 -1
  111. package/dist/features/products/components/AuctionsIndexListing.js +61 -9
  112. package/dist/features/products/components/InteractiveProductCard.d.ts +2 -4
  113. package/dist/features/products/components/InteractiveProductCard.js +2 -2
  114. package/dist/features/products/components/ProductDetailPageView.d.ts +1 -1
  115. package/dist/features/products/components/ProductDetailPageView.js +116 -25
  116. package/dist/features/products/components/ProductFilters.d.ts +6 -11
  117. package/dist/features/products/components/ProductFilters.js +5 -3
  118. package/dist/features/products/components/ProductGrid.d.ts +8 -2
  119. package/dist/features/products/components/ProductGrid.js +20 -5
  120. package/dist/features/products/components/ProductTabsShell.d.ts +3 -11
  121. package/dist/features/products/components/ProductTabsShell.js +14 -14
  122. package/dist/features/products/components/ProductsIndexListing.js +73 -9
  123. package/dist/features/products/components/ProductsIndexPageView.d.ts +6 -1
  124. package/dist/features/products/components/ProductsIndexPageView.js +39 -6
  125. package/dist/features/products/components/RelatedProductsCarousel.d.ts +7 -0
  126. package/dist/features/products/components/RelatedProductsCarousel.js +11 -0
  127. package/dist/features/products/components/index.d.ts +1 -0
  128. package/dist/features/products/components/index.js +1 -0
  129. package/dist/features/products/hooks/useProducts.js +16 -0
  130. package/dist/features/products/repository/products.repository.d.ts +8 -0
  131. package/dist/features/products/repository/products.repository.js +2 -0
  132. package/dist/features/products/schemas/index.d.ts +8 -8
  133. package/dist/features/products/types/index.d.ts +12 -0
  134. package/dist/features/promotions/components/CouponsIndexListing.d.ts +9 -0
  135. package/dist/features/promotions/components/CouponsIndexListing.js +86 -0
  136. package/dist/features/promotions/components/PromotionsView.d.ts +11 -5
  137. package/dist/features/promotions/components/PromotionsView.js +6 -1
  138. package/dist/features/promotions/components/index.d.ts +4 -2
  139. package/dist/features/promotions/components/index.js +2 -1
  140. package/dist/features/reviews/components/ReviewDetailPageView.d.ts +4 -0
  141. package/dist/features/reviews/components/ReviewDetailPageView.js +20 -0
  142. package/dist/features/reviews/components/ReviewDetailShell.d.ts +7 -0
  143. package/dist/features/reviews/components/ReviewDetailShell.js +80 -0
  144. package/dist/features/reviews/components/ReviewFilters.d.ts +3 -3
  145. package/dist/features/reviews/components/ReviewFilters.js +5 -4
  146. package/dist/features/reviews/components/ReviewsIndexListing.d.ts +4 -3
  147. package/dist/features/reviews/components/ReviewsIndexListing.js +35 -51
  148. package/dist/features/reviews/components/ReviewsIndexPageView.d.ts +6 -1
  149. package/dist/features/reviews/components/ReviewsIndexPageView.js +49 -3
  150. package/dist/features/reviews/components/ReviewsList.js +9 -1
  151. package/dist/features/reviews/components/index.d.ts +1 -0
  152. package/dist/features/reviews/hooks/useReviews.js +15 -1
  153. package/dist/features/reviews/types/index.d.ts +6 -1
  154. package/dist/features/seller/components/SellerSidebar.d.ts +8 -4
  155. package/dist/features/seller/components/SellerSidebar.js +6 -4
  156. package/dist/features/seller/components/index.d.ts +30 -0
  157. package/dist/features/seller/components/index.js +17 -0
  158. package/dist/features/seller/hooks/useSellerStore.d.ts +2 -0
  159. package/dist/features/seller/hooks/useSellerStore.js +2 -0
  160. package/dist/features/seller/permission-map.d.ts +4 -2
  161. package/dist/features/seller/permission-map.js +16 -14
  162. package/dist/features/seller/schemas/index.d.ts +2 -2
  163. package/dist/features/stores/api/[storeSlug]/reviews/route.d.ts +1 -1
  164. package/dist/features/stores/api/[storeSlug]/reviews/route.js +24 -19
  165. package/dist/features/stores/components/InteractiveStoreCard.d.ts +0 -5
  166. package/dist/features/stores/components/InteractiveStoreCard.js +9 -9
  167. package/dist/features/stores/components/StoreAuctionsListing.js +27 -9
  168. package/dist/features/stores/components/StoreDetailLayoutView.js +2 -0
  169. package/dist/features/stores/components/StoreFilters.d.ts +5 -0
  170. package/dist/features/stores/components/StoreFilters.js +20 -0
  171. package/dist/features/stores/components/StoreHeader.js +2 -2
  172. package/dist/features/stores/components/StorePreOrdersListing.d.ts +5 -0
  173. package/dist/features/stores/components/StorePreOrdersListing.js +40 -0
  174. package/dist/features/stores/components/StorePreOrdersPageView.d.ts +4 -0
  175. package/dist/features/stores/components/StorePreOrdersPageView.js +21 -0
  176. package/dist/features/stores/components/StoreProductsListing.js +21 -11
  177. package/dist/features/stores/components/StoreReviewsListing.js +2 -7
  178. package/dist/features/stores/components/StoresIndexListing.js +42 -8
  179. package/dist/features/stores/components/StoresIndexPageView.d.ts +6 -1
  180. package/dist/features/stores/components/StoresIndexPageView.js +9 -2
  181. package/dist/features/stores/components/index.d.ts +3 -0
  182. package/dist/features/stores/components/index.js +1 -0
  183. package/dist/features/stores/hooks/useStores.d.ts +7 -1
  184. package/dist/features/stores/hooks/useStores.js +16 -3
  185. package/dist/features/stores/schemas/index.d.ts +2 -2
  186. package/dist/features/stores/types/index.d.ts +3 -0
  187. package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +20 -0
  188. package/dist/features/wishlist/hooks/useGuestWishlist.js +49 -0
  189. package/dist/features/wishlist/hooks/useWishlistCount.d.ts +7 -0
  190. package/dist/features/wishlist/hooks/useWishlistCount.js +31 -0
  191. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +56 -0
  192. package/dist/features/wishlist/hooks/useWishlistWithGuest.js +57 -0
  193. package/dist/features/wishlist/index.d.ts +3 -0
  194. package/dist/features/wishlist/index.js +3 -0
  195. package/dist/features/wishlist/utils/guest-wishlist.d.ts +22 -0
  196. package/dist/features/wishlist/utils/guest-wishlist.js +70 -0
  197. package/dist/index.d.ts +50 -1
  198. package/dist/index.js +63 -1
  199. package/dist/next/routing/route-map.d.ts +70 -36
  200. package/dist/next/routing/route-map.js +30 -22
  201. package/dist/seed/addresses-seed-data.js +62 -261
  202. package/dist/seed/beyblade-seed-data.d.ts +7 -0
  203. package/dist/seed/beyblade-seed-data.js +947 -0
  204. package/dist/seed/bids-seed-data.d.ts +10 -2
  205. package/dist/seed/bids-seed-data.js +220 -1071
  206. package/dist/seed/blog-posts-seed-data.d.ts +2 -2
  207. package/dist/seed/blog-posts-seed-data.js +455 -117
  208. package/dist/seed/cart-seed-data.d.ts +9 -9
  209. package/dist/seed/cart-seed-data.js +73 -74
  210. package/dist/seed/coupons-seed-data.d.ts +3 -4
  211. package/dist/seed/coupons-seed-data.js +3 -509
  212. package/dist/seed/events-seed-data.d.ts +2 -2
  213. package/dist/seed/events-seed-data.js +315 -476
  214. package/dist/seed/faq-seed-data.d.ts +18 -41
  215. package/dist/seed/faq-seed-data.js +1059 -1172
  216. package/dist/seed/hot-wheels-seed-data.d.ts +7 -0
  217. package/dist/seed/hot-wheels-seed-data.js +1365 -0
  218. package/dist/seed/index.d.ts +6 -1
  219. package/dist/seed/index.js +6 -1
  220. package/dist/seed/pokemon-carousel-slides-seed-data.d.ts +4 -2
  221. package/dist/seed/pokemon-carousel-slides-seed-data.js +152 -268
  222. package/dist/seed/pokemon-categories-seed-data.d.ts +18 -21
  223. package/dist/seed/pokemon-categories-seed-data.js +424 -1004
  224. package/dist/seed/pokemon-coupons-seed-data.d.ts +6 -0
  225. package/dist/seed/pokemon-coupons-seed-data.js +465 -0
  226. package/dist/seed/pokemon-homepage-sections-seed-data.d.ts +3 -2
  227. package/dist/seed/pokemon-homepage-sections-seed-data.js +67 -289
  228. package/dist/seed/pokemon-products-seed-data.js +662 -0
  229. package/dist/seed/pokemon-seed-bundle.d.ts +32 -11
  230. package/dist/seed/pokemon-seed-bundle.js +41 -11
  231. package/dist/seed/pokemon-stores-seed-data.d.ts +2 -3
  232. package/dist/seed/pokemon-stores-seed-data.js +56 -31
  233. package/dist/seed/pokemon-users-seed-data.d.ts +2 -2
  234. package/dist/seed/pokemon-users-seed-data.js +245 -261
  235. package/dist/seed/reviews-seed-data.d.ts +17 -2
  236. package/dist/seed/reviews-seed-data.js +519 -483
  237. package/dist/seed/site-settings-seed-data.js +14 -14
  238. package/dist/seed/store-addresses-seed-data.js +68 -50
  239. package/dist/seed/transformers-seed-data.d.ts +7 -0
  240. package/dist/seed/transformers-seed-data.js +510 -0
  241. package/dist/seed/wishlists-seed-data.d.ts +5 -1
  242. package/dist/seed/wishlists-seed-data.js +82 -4
  243. package/dist/server.d.ts +1 -0
  244. package/dist/server.js +2 -0
  245. package/dist/tokens/index.d.ts +6 -0
  246. package/dist/tokens/index.js +2 -0
  247. package/dist/ui/components/BaseListingCard.js +24 -26
  248. package/dist/ui/components/BaseListingCard.style.css +5 -5
  249. package/dist/ui/components/HorizontalScroller.d.ts +1 -1
  250. package/dist/ui/components/HorizontalScroller.js +19 -5
  251. package/dist/ui/components/SideDrawer.style.css +3 -11
  252. package/dist/ui/rich-text/RichText.js +19 -1
  253. package/package.json +1 -1
package/dist/client.d.ts CHANGED
@@ -59,10 +59,13 @@ export type { NavigationLoaderProps } from "./ui/index";
59
59
  export { ZodSetup } from "./validation/ZodSetup";
60
60
  export type { ZodSetupProps } from "./validation/ZodSetup";
61
61
  export { AdminSidebar } from "./features/admin/components/AdminSidebar";
62
- export { AdminDashboardView, AdminAnalyticsView } from "./features/admin/index";
62
+ export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
63
63
  export type { AdminDashboardViewProps, AdminAnalyticsViewProps, AdminAnalyticsViewLabels } from "./features/admin/index";
64
+ export { ADMIN_ENDPOINTS } from "./constants/index";
64
65
  export { UserSidebar } from "./features/account/components/UserSidebar";
65
- export type { UserSidebarProps, UserNavItem } from "./features/account/components/UserSidebar";
66
+ export type { UserSidebarProps, UserNavItem, UserNavGroup } from "./features/account/components/UserSidebar";
67
+ export { CouponsIndexListing } from "./features/promotions/components/CouponsIndexListing";
68
+ export type { CouponsIndexListingProps } from "./features/promotions/components/CouponsIndexListing";
66
69
  export { NotificationBell } from "./features/account/components/NotificationBell";
67
70
  export { ProtectedRoute, AuthStatusPanel, ForgotPasswordView, LoginForm, RegisterForm, ResetPasswordView, VerifyEmailView } from "./features/auth/index";
68
71
  export type { AuthGuardUser, ForgotPasswordViewProps, LoginFormProps, LoginFormValues, RegisterFormProps, RegisterFormValues, ResetPasswordViewProps, VerifyEmailViewProps, } from "./features/auth/index";
@@ -76,19 +79,20 @@ export { CategoryProductsView, CategoriesListView } from "./features/categories/
76
79
  export type { CategoryItem } from "./features/categories/index";
77
80
  export { MediaImage } from "./features/media/index";
78
81
  export { ReviewsListView } from "./features/reviews/index";
79
- export { SellerSidebar } from "./features/seller/components/SellerSidebar";
80
- export type { SellerNavItem } from "./features/seller/components/SellerSidebar";
82
+ export { StoreSidebar, SellerSidebar } from "./features/seller/components/SellerSidebar";
83
+ export type { StoreNavItem, SellerNavItem } from "./features/seller/components/SellerSidebar";
81
84
  export { StoreProductsView } from "./features/stores/index";
82
85
  export type { StoreProductItem } from "./features/stores/index";
83
86
  export { AdSlot } from "./features/homepage/components/AdSlot";
84
87
  export { registerAdSlot, registerAdSlots, unregisterAdSlot, clearAdRegistry, setAdConsentGranted, isAdConsentGranted, isAdSlotRenderable, } from "./features/homepage/ad-registry";
85
88
  export type { AdSlotId, AdProvider, AdSlotConfig } from "./features/homepage/ad-registry";
86
- export { WishlistView } from "./features/wishlist/index";
87
- export type { WishlistViewProps } from "./features/wishlist/index";
89
+ export { WishlistView, useGuestWishlist, useWishlistWithGuest } from "./features/wishlist/index";
90
+ export type { WishlistViewProps, GuestWishlistItem } from "./features/wishlist/index";
91
+ export { getGuestWishlistItems, addToGuestWishlist, removeFromGuestWishlist, isInGuestWishlist, clearGuestWishlist, getGuestWishlistCount, getGuestWishlistByType, } from "./features/wishlist/utils/guest-wishlist";
88
92
  export { InteractiveProductCard } from "./features/products/index";
89
93
  export type { InteractiveProductCardProps } from "./features/products/index";
90
- export { SellerDashboardView, useSellerDashboard } from "./features/seller/index";
91
- export type { SellerDashboardViewProps } from "./features/seller/index";
94
+ export { SellerDashboardView as StoreDashboardView, SellerDashboardView, useSellerDashboard as useStoreDashboard, useSellerDashboard } from "./features/seller/index";
95
+ export type { SellerDashboardViewProps as StoreDashboardViewProps, SellerDashboardViewProps } from "./features/seller/index";
92
96
  export { UserAccountHubView, UserOrdersView } from "./features/account/index";
93
97
  export type { UserAccountHubViewProps, UserAccountHubViewLabels, UserOrdersViewProps, UserOrdersViewLabels } from "./features/account/index";
94
98
  export { useOrders, OrdersList } from "./features/orders/index";
package/dist/client.js CHANGED
@@ -121,8 +121,10 @@ export { Search } from "./features/search/components";
121
121
  export { ToastProvider, SkipToMain, NavigationLoader } from "./ui/index";
122
122
  export { ZodSetup } from "./validation/ZodSetup";
123
123
  export { AdminSidebar } from "./features/admin/components/AdminSidebar";
124
- export { AdminDashboardView, AdminAnalyticsView } from "./features/admin/index";
124
+ export { AdminDashboardView, AdminAnalyticsView, AdminListingScaffold, useAdminListingData, toRecordArray, toStringValue, toRelativeDate, toRupees } from "./features/admin/index";
125
+ export { ADMIN_ENDPOINTS } from "./constants/index";
125
126
  export { UserSidebar } from "./features/account/components/UserSidebar";
127
+ export { CouponsIndexListing } from "./features/promotions/components/CouponsIndexListing";
126
128
  export { NotificationBell } from "./features/account/components/NotificationBell";
127
129
  export { ProtectedRoute, AuthStatusPanel, ForgotPasswordView, LoginForm, RegisterForm, ResetPasswordView, VerifyEmailView } from "./features/auth/index";
128
130
  export { useLogout, useLogin, useGoogleLogin, useRegister, useForgotPassword, useResetPassword, useVerifyEmail } from "./features/auth/index";
@@ -131,13 +133,14 @@ export { useAddresses } from "./features/account/index";
131
133
  export { CategoryProductsView, CategoriesListView } from "./features/categories/index";
132
134
  export { MediaImage } from "./features/media/index";
133
135
  export { ReviewsListView } from "./features/reviews/index";
134
- export { SellerSidebar } from "./features/seller/components/SellerSidebar";
136
+ export { StoreSidebar, SellerSidebar } from "./features/seller/components/SellerSidebar";
135
137
  export { StoreProductsView } from "./features/stores/index";
136
138
  export { AdSlot } from "./features/homepage/components/AdSlot";
137
139
  export { registerAdSlot, registerAdSlots, unregisterAdSlot, clearAdRegistry, setAdConsentGranted, isAdConsentGranted, isAdSlotRenderable, } from "./features/homepage/ad-registry";
138
- export { WishlistView } from "./features/wishlist/index";
140
+ export { WishlistView, useGuestWishlist, useWishlistWithGuest } from "./features/wishlist/index";
141
+ export { getGuestWishlistItems, addToGuestWishlist, removeFromGuestWishlist, isInGuestWishlist, clearGuestWishlist, getGuestWishlistCount, getGuestWishlistByType, } from "./features/wishlist/utils/guest-wishlist";
139
142
  export { InteractiveProductCard } from "./features/products/index";
140
- export { SellerDashboardView, useSellerDashboard } from "./features/seller/index";
143
+ export { SellerDashboardView as StoreDashboardView, SellerDashboardView, useSellerDashboard as useStoreDashboard, useSellerDashboard } from "./features/seller/index";
141
144
  export { UserAccountHubView, UserOrdersView } from "./features/account/index";
142
145
  export { useOrders, OrdersList } from "./features/orders/index";
143
146
  export { useCouponValidate } from "./features/promotions/hooks/useCouponValidate";
@@ -71,6 +71,8 @@ export declare const ADMIN_ENDPOINTS: {
71
71
  readonly EVENT_ENTRY_BY_ID: (eventId: string, entryId: string) => string;
72
72
  readonly COUPONS: "/api/admin/coupons";
73
73
  readonly SECTIONS: "/api/admin/sections";
74
+ readonly NEWSLETTER: "/api/admin/newsletter";
75
+ readonly CONTACT_SUBMISSIONS: "/api/admin/contact-submissions";
74
76
  };
75
77
  export declare const CHAT_ENDPOINTS: {
76
78
  readonly LIST: "/api/chat";
@@ -284,6 +286,8 @@ export declare const API_ENDPOINTS: {
284
286
  readonly EVENT_ENTRY_BY_ID: (eventId: string, entryId: string) => string;
285
287
  readonly COUPONS: "/api/admin/coupons";
286
288
  readonly SECTIONS: "/api/admin/sections";
289
+ readonly NEWSLETTER: "/api/admin/newsletter";
290
+ readonly CONTACT_SUBMISSIONS: "/api/admin/contact-submissions";
287
291
  };
288
292
  readonly CHAT: {
289
293
  readonly LIST: "/api/chat";
@@ -89,6 +89,8 @@ export const ADMIN_ENDPOINTS = {
89
89
  EVENT_ENTRY_BY_ID: (eventId, entryId) => `/api/admin/events/${eventId}/entries/${entryId}`,
90
90
  COUPONS: "/api/admin/coupons",
91
91
  SECTIONS: "/api/admin/sections",
92
+ NEWSLETTER: "/api/admin/newsletter",
93
+ CONTACT_SUBMISSIONS: "/api/admin/contact-submissions",
92
94
  };
93
95
  // ---------------------------------------------------------------------------
94
96
  // Chat
@@ -0,0 +1,32 @@
1
+ import type { IRepository, PagedResult } from "../contracts/repository";
2
+ export interface ContactSubmissionDocument {
3
+ id: string;
4
+ name: string;
5
+ email: string;
6
+ subject: string;
7
+ message: string;
8
+ status: "new" | "read" | "resolved";
9
+ ipAddress?: string;
10
+ createdAt: Date;
11
+ updatedAt?: Date;
12
+ }
13
+ export type ContactSubmissionCreateInput = Omit<ContactSubmissionDocument, "id" | "status" | "createdAt" | "updatedAt">;
14
+ export interface ContactSubmissionListModel {
15
+ filters?: string;
16
+ sorts?: string;
17
+ page?: string;
18
+ pageSize?: string;
19
+ }
20
+ export declare const CONTACT_SUBMISSIONS_COLLECTION: "contactSubmissions";
21
+ export declare class ContactSubmissionsRepository {
22
+ private _repo;
23
+ constructor(repo?: IRepository<ContactSubmissionDocument> | null);
24
+ private get repo();
25
+ list(model: ContactSubmissionListModel): Promise<PagedResult<ContactSubmissionDocument>>;
26
+ findById(id: string): Promise<ContactSubmissionDocument | null>;
27
+ save(input: ContactSubmissionCreateInput): Promise<ContactSubmissionDocument>;
28
+ markRead(id: string): Promise<void>;
29
+ markResolved(id: string): Promise<void>;
30
+ deleteById(id: string): Promise<void>;
31
+ }
32
+ export declare const contactSubmissionsRepository: ContactSubmissionsRepository;
@@ -0,0 +1,49 @@
1
+ import { getProviders } from "../contracts/registry";
2
+ export const CONTACT_SUBMISSIONS_COLLECTION = "contactSubmissions";
3
+ function resolveRepository() {
4
+ const provider = getProviders().db;
5
+ if (!provider) {
6
+ throw new Error("DB provider is not registered. Configure providers before using ContactSubmissionsRepository.");
7
+ }
8
+ return provider.getRepository(CONTACT_SUBMISSIONS_COLLECTION);
9
+ }
10
+ export class ContactSubmissionsRepository {
11
+ constructor(repo = null) {
12
+ this._repo = repo;
13
+ }
14
+ get repo() {
15
+ if (!this._repo) {
16
+ this._repo = resolveRepository();
17
+ }
18
+ return this._repo;
19
+ }
20
+ async list(model) {
21
+ const page = Number(model.page || "1");
22
+ const perPage = Number(model.pageSize || "50");
23
+ return this.repo.findAll({
24
+ filters: model.filters,
25
+ sort: model.sorts || "-createdAt",
26
+ page: Number.isFinite(page) ? page : 1,
27
+ perPage: Number.isFinite(perPage) ? perPage : 50,
28
+ });
29
+ }
30
+ async findById(id) {
31
+ return this.repo.findById(id);
32
+ }
33
+ async save(input) {
34
+ return this.repo.create({
35
+ ...input,
36
+ status: "new",
37
+ });
38
+ }
39
+ async markRead(id) {
40
+ await this.repo.update(id, { status: "read", updatedAt: new Date() });
41
+ }
42
+ async markResolved(id) {
43
+ await this.repo.update(id, { status: "resolved", updatedAt: new Date() });
44
+ }
45
+ async deleteById(id) {
46
+ await this.repo.delete(id);
47
+ }
48
+ }
49
+ export const contactSubmissionsRepository = new ContactSubmissionsRepository();
@@ -22,6 +22,8 @@ export { COPILOT_LOGS_COLLECTION, COPILOT_LOGS_INDEXED_FIELDS, copilotLogQueryHe
22
22
  export { useSiteSettings } from "./hooks/useSiteSettings";
23
23
  export { NEWSLETTER_SUBSCRIBER_FIELDS, NEWSLETTER_SUBSCRIBERS_COLLECTION, NEWSLETTER_SUBSCRIBER_INDEXED_FIELDS, newsletterRepository, } from "./newsletter.repository";
24
24
  export type { NewsletterSubscriberDocument, NewsletterSubscriberCreateInput, NewsletterSubscriberUpdateInput, } from "./newsletter.repository";
25
+ export { CONTACT_SUBMISSIONS_COLLECTION, contactSubmissionsRepository, } from "./contact-submissions.repository";
26
+ export type { ContactSubmissionDocument, ContactSubmissionCreateInput, } from "./contact-submissions.repository";
25
27
  export { subscribeNewsletter, type SubscribeNewsletterActionInput, type SupportedNewsletterSource, } from "./newsletter-actions";
26
28
  export { unitOfWork } from "./unit-of-work";
27
29
  export type { UnitOfWork } from "./unit-of-work";
@@ -14,6 +14,7 @@ export { CopilotLogRepository, copilotLogRepository, } from "./copilot-log.repos
14
14
  export { COPILOT_LOGS_COLLECTION, COPILOT_LOGS_INDEXED_FIELDS, copilotLogQueryHelpers, } from "./copilot-log.repository";
15
15
  export { useSiteSettings } from "./hooks/useSiteSettings";
16
16
  export { NEWSLETTER_SUBSCRIBER_FIELDS, NEWSLETTER_SUBSCRIBERS_COLLECTION, NEWSLETTER_SUBSCRIBER_INDEXED_FIELDS, newsletterRepository, } from "./newsletter.repository";
17
+ export { CONTACT_SUBMISSIONS_COLLECTION, contactSubmissionsRepository, } from "./contact-submissions.repository";
17
18
  export { subscribeNewsletter, } from "./newsletter-actions";
18
19
  export { unitOfWork } from "./unit-of-work";
19
20
  export { createServerAction, setActionMiddleware, _resetActionMiddleware, } from "./server-action";
@@ -83,5 +83,5 @@ export async function HowPayoutsWorkView({ heroBannerClass = DEFAULT_HERO_CLASS,
83
83
  desc: t("diagramStep5Desc"),
84
84
  },
85
85
  ];
86
- return (_jsxs("div", { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", "data-section": "howpayoutsworkview-div-151", children: [_jsx(Section, { className: `${heroBannerClass} text-white py-14 md:py-16 lg:py-20`, children: _jsxs("div", { className: `${page.container.md} text-center`, "data-section": "howpayoutsworkview-div-152", children: [_jsx(Heading, { level: 1, variant: "none", className: "mb-4 text-white", children: t("title") }), _jsx(Text, { variant: "none", className: "text-white/80 max-w-2xl mx-auto", children: t("subtitle") })] }) }), _jsxs("div", { className: `${page.container.md} py-10 md:py-12 lg:py-16 space-y-14`, "data-section": "howpayoutsworkview-div-153", children: [_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-8 text-center", children: t("stepsTitle") }), _jsx(Stack, { gap: "md", className: "gap-5", children: STEPS.map(({ number, icon, title, text }) => (_jsxs("div", { className: `flex items-start gap-4 p-5 rounded-xl border ${themed.border} ${themed.bgPrimary}`, "data-section": "howpayoutsworkview-div-154", children: [_jsx("div", { className: `flex-shrink-0 w-10 h-10 rounded-full bg-primary/10 dark:bg-primary/15 ${flex.center} text-xl`, "data-section": "howpayoutsworkview-div-155", children: icon }), _jsxs("div", { "data-section": "howpayoutsworkview-div-156", children: [_jsxs(Text, { className: "font-semibold mb-0.5", children: [number, ". ", title] }), _jsx(Text, { variant: "secondary", className: "text-sm leading-relaxed", children: text })] })] }, number))) })] }), _jsx(Section, { children: _jsx(FlowDiagram, { title: `💸 ${t("diagramTitle")}`, titleClass: "text-primary", connectorClass: "bg-primary/20 dark:bg-primary/30", steps: DIAGRAM_STEPS, centered: true }) }), _jsx(Section, { children: _jsx("div", { className: "grid gap-5 md:grid-cols-2", "data-section": "howpayoutsworkview-div-157", children: INFO_CARDS.map(({ icon: Icon, title, text, color, iconColor }) => (_jsxs("div", { className: `rounded-xl border p-5 ${color}`, "data-section": "howpayoutsworkview-div-158", children: [_jsx("div", { className: `w-10 h-10 rounded-lg bg-white/60 dark:bg-white/10 ${flex.center} mb-3`, "data-section": "howpayoutsworkview-div-159", children: _jsx(Icon, { className: `w-5 h-5 ${iconColor}` }) }), _jsx(Text, { className: "font-semibold mb-1", children: title }), _jsx(Text, { variant: "secondary", className: "text-sm leading-relaxed", children: text })] }, title))) }) }), _jsxs(Section, { className: `rounded-2xl p-8 text-center ${themed.bgSecondary} border ${themed.border}`, children: [_jsx(Heading, { level: 2, className: "mb-3", children: t("ctaTitle") }), _jsx(Text, { variant: "secondary", className: "mb-6 max-w-lg mx-auto", children: t("ctaText") }), _jsxs("div", { className: `${flex.center} gap-4 flex-wrap`, "data-section": "howpayoutsworkview-div-160", children: [_jsx(TextLink, { href: String(ROUTES.SELLER.PAYOUT_SETTINGS), children: t("ctaPayoutSettings") }), _jsx(TextLink, { href: String(ROUTES.PUBLIC.FEES), variant: "muted", children: t("ctaFees") })] })] })] })] }));
86
+ return (_jsxs("div", { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", "data-section": "howpayoutsworkview-div-151", children: [_jsx(Section, { className: `${heroBannerClass} text-white py-14 md:py-16 lg:py-20`, children: _jsxs("div", { className: `${page.container.md} text-center`, "data-section": "howpayoutsworkview-div-152", children: [_jsx(Heading, { level: 1, variant: "none", className: "mb-4 text-white", children: t("title") }), _jsx(Text, { variant: "none", className: "text-white/80 max-w-2xl mx-auto", children: t("subtitle") })] }) }), _jsxs("div", { className: `${page.container.md} py-10 md:py-12 lg:py-16 space-y-14`, "data-section": "howpayoutsworkview-div-153", children: [_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-8 text-center", children: t("stepsTitle") }), _jsx(Stack, { gap: "md", className: "gap-5", children: STEPS.map(({ number, icon, title, text }) => (_jsxs("div", { className: `flex items-start gap-4 p-5 rounded-xl border ${themed.border} ${themed.bgPrimary}`, "data-section": "howpayoutsworkview-div-154", children: [_jsx("div", { className: `flex-shrink-0 w-10 h-10 rounded-full bg-primary/10 dark:bg-primary/15 ${flex.center} text-xl`, "data-section": "howpayoutsworkview-div-155", children: icon }), _jsxs("div", { "data-section": "howpayoutsworkview-div-156", children: [_jsxs(Text, { className: "font-semibold mb-0.5", children: [number, ". ", title] }), _jsx(Text, { variant: "secondary", className: "text-sm leading-relaxed", children: text })] })] }, number))) })] }), _jsx(Section, { children: _jsx(FlowDiagram, { title: `💸 ${t("diagramTitle")}`, titleClass: "text-primary", connectorClass: "bg-primary/20 dark:bg-primary/30", steps: DIAGRAM_STEPS, centered: true }) }), _jsx(Section, { children: _jsx("div", { className: "grid gap-5 md:grid-cols-2", "data-section": "howpayoutsworkview-div-157", children: INFO_CARDS.map(({ icon: Icon, title, text, color, iconColor }) => (_jsxs("div", { className: `rounded-xl border p-5 ${color}`, "data-section": "howpayoutsworkview-div-158", children: [_jsx("div", { className: `w-10 h-10 rounded-lg bg-white/60 dark:bg-white/10 ${flex.center} mb-3`, "data-section": "howpayoutsworkview-div-159", children: _jsx(Icon, { className: `w-5 h-5 ${iconColor}` }) }), _jsx(Text, { className: "font-semibold mb-1", children: title }), _jsx(Text, { variant: "secondary", className: "text-sm leading-relaxed", children: text })] }, title))) }) }), _jsxs(Section, { className: `rounded-2xl p-8 text-center ${themed.bgSecondary} border ${themed.border}`, children: [_jsx(Heading, { level: 2, className: "mb-3", children: t("ctaTitle") }), _jsx(Text, { variant: "secondary", className: "mb-6 max-w-lg mx-auto", children: t("ctaText") }), _jsxs("div", { className: `${flex.center} gap-4 flex-wrap`, "data-section": "howpayoutsworkview-div-160", children: [_jsx(TextLink, { href: String(ROUTES.STORE.PAYOUT_SETTINGS), children: t("ctaPayoutSettings") }), _jsx(TextLink, { href: String(ROUTES.PUBLIC.FEES), variant: "muted", children: t("ctaFees") })] })] })] })] }));
87
87
  }
@@ -0,0 +1,5 @@
1
+ import type { UrlTable } from "../../filters/FilterPanel";
2
+ export interface AddressFiltersProps {
3
+ table: UrlTable;
4
+ }
5
+ export declare function AddressFilters({ table }: AddressFiltersProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTranslations } from "next-intl";
3
+ import { FilterFacetSection } from "../../filters/FilterFacetSection";
4
+ import { SwitchFilter } from "../../filters/SwitchFilter";
5
+ import { Div } from "../../../ui";
6
+ export function AddressFilters({ table }) {
7
+ const t = useTranslations("filters");
8
+ const typeOptions = [
9
+ { value: "home", label: t("addressTypeHome") },
10
+ { value: "work", label: t("addressTypeWork") },
11
+ { value: "shipping", label: t("addressTypeShipping") },
12
+ { value: "billing", label: t("addressTypeBilling") },
13
+ { value: "business", label: t("addressTypeBusiness") },
14
+ { value: "other", label: t("addressTypeOther") },
15
+ ];
16
+ const selectedTypes = table.get("addressType")
17
+ ? table.get("addressType").split("|").filter(Boolean)
18
+ : [];
19
+ return (_jsxs(Div, { children: [_jsx(FilterFacetSection, { title: t("addressType"), options: typeOptions, selected: selectedTypes, onChange: (vals) => table.set("addressType", vals.join("|")), searchable: false, defaultCollapsed: false }), _jsx(SwitchFilter, { title: t("addressVerified"), label: t("showVerifiedAddressOnly"), checked: table.get("verified") === "true", onChange: (v) => table.set("verified", v ? "true" : ""), defaultCollapsed: true }), _jsx(SwitchFilter, { title: t("addressActive"), label: t("showActiveAddressOnly"), checked: table.get("activeOnly") === "true", onChange: (v) => table.set("activeOnly", v ? "true" : ""), defaultCollapsed: true })] }));
20
+ }
@@ -0,0 +1,6 @@
1
+ export interface AddressesIndexListingProps {
2
+ onAdd?: () => void;
3
+ onEdit?: (address: any) => void;
4
+ onDelete?: (id: string) => void;
5
+ }
6
+ export declare function AddressesIndexListing({ onAdd, onEdit, onDelete, }: AddressesIndexListingProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Search, SlidersHorizontal, X } from "lucide-react";
5
+ import { useAddresses } from "../hooks/useAddresses";
6
+ import { AddressBook } from "./AddressBook";
7
+ import { AddressFilters } from "./AddressFilters";
8
+ function createLocalTable(params, setParams) {
9
+ return {
10
+ get: (key) => params[key] ?? "",
11
+ set: (key, value) => setParams({ ...params, [key]: value }),
12
+ setMany: (updates) => setParams({ ...params, ...updates }),
13
+ getNumber: (key, def) => {
14
+ const v = params[key];
15
+ return v ? Number(v) : def;
16
+ },
17
+ setPage: (page) => setParams({ ...params, page: String(page) }),
18
+ setSort: (sort) => setParams({ ...params, sort }),
19
+ setPageSize: (size) => setParams({ ...params, pageSize: String(size) }),
20
+ clear: (keys) => {
21
+ const next = { ...params };
22
+ (Array.isArray(keys) ? keys : [keys]).forEach((k) => delete next[k]);
23
+ setParams(next);
24
+ },
25
+ buildSieveParams: () => ({}),
26
+ buildSearchParams: () => new URLSearchParams(),
27
+ };
28
+ }
29
+ export function AddressesIndexListing({ onAdd, onEdit, onDelete, }) {
30
+ const [searchInput, setSearchInput] = useState("");
31
+ const [activeSearch, setActiveSearch] = useState("");
32
+ const [filterOpen, setFilterOpen] = useState(false);
33
+ const [filterParams, setFilterParams] = useState({});
34
+ const table = createLocalTable(filterParams, setFilterParams);
35
+ const { data: addresses = [], isLoading } = useAddresses({
36
+ filters: {
37
+ q: activeSearch || undefined,
38
+ addressType: filterParams.addressType || undefined,
39
+ verified: filterParams.verified === "true" || undefined,
40
+ activeOnly: filterParams.activeOnly === "true" || undefined,
41
+ },
42
+ });
43
+ const commitSearch = () => {
44
+ setActiveSearch(searchInput.trim());
45
+ };
46
+ const closeFilters = () => setFilterOpen(false);
47
+ if (isLoading) {
48
+ return (_jsx("div", { className: "grid sm:grid-cols-2 gap-4", children: Array.from({ length: 4 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-200 dark:border-slate-700 animate-pulse p-4 space-y-2", children: [_jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) }));
49
+ }
50
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", onClick: () => setFilterOpen(true), className: "flex shrink-0 items-center gap-1.5 rounded-lg border border-zinc-300 dark:border-slate-600 px-3 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: "Filters" })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && commitSearch(), placeholder: "Search by address, postcode or label...", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); setActiveSearch(""); }, className: "px-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] })] }), addresses.length === 0 ? (_jsx("p", { className: "py-8 text-center text-sm text-zinc-500 dark:text-zinc-400", children: activeSearch ? `No addresses matching "${activeSearch}"` : "No saved addresses." })) : (_jsx(AddressBook, { addresses: addresses, onEdit: onEdit, onDelete: onDelete, onAdd: onAdd })), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: closeFilters }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: closeFilters, "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(AddressFilters, { table: table }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsx("button", { type: "button", onClick: closeFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply filters" }) })] })] }))] }));
51
+ }
@@ -4,12 +4,16 @@ export interface UserNavItem {
4
4
  label: string;
5
5
  icon?: React.ReactNode;
6
6
  }
7
+ export interface UserNavGroup {
8
+ title: string;
9
+ items: UserNavItem[];
10
+ defaultOpen?: boolean;
11
+ }
7
12
  export interface UserSidebarProps {
8
13
  items: UserNavItem[];
9
- /** Whether the mobile drawer is open */
14
+ groups?: UserNavGroup[];
10
15
  mobileOpen?: boolean;
11
- /** Called when the mobile drawer should close */
12
16
  onCloseMobile?: () => void;
13
17
  className?: string;
14
18
  }
15
- export declare function UserSidebar({ items, mobileOpen, onCloseMobile, className, }: UserSidebarProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function UserSidebar({ items, groups, mobileOpen, onCloseMobile, className, }: UserSidebarProps): import("react/jsx-runtime").JSX.Element;
@@ -1,18 +1,66 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useEffect, useCallback } from "react";
3
4
  import Link from "next/link";
4
5
  import { usePathname } from "next/navigation";
5
6
  import { Aside, Li, Nav, Span, Ul } from "../../../ui";
6
7
  import { BottomSheet } from "../../layout/BottomSheet";
7
- function SidebarContent({ items, activeHref, onItemClick, }) {
8
- return (_jsx(Nav, { "aria-label": "User navigation", className: "flex-1 overflow-y-auto py-3", children: _jsx(Ul, { className: "space-y-0.5 px-2", children: items.map((item) => {
8
+ const STORAGE_KEY = "user-sidebar-collapsed";
9
+ function NavLink({ item, isActive, collapsed, onClick, }) {
10
+ return (_jsxs(Link, { href: item.href, onClick: onClick, title: collapsed ? item.label : undefined, className: `flex items-center rounded-lg py-2 text-sm transition-colors ${collapsed ? "justify-center px-2" : "gap-3 px-3"} ${isActive
11
+ ? "bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400 font-medium"
12
+ : "text-zinc-600 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800 hover:text-zinc-900 dark:hover:text-zinc-100"}`, children: [item.icon && _jsx(Span, { className: "shrink-0 text-[1.1rem]", children: item.icon }), !collapsed && _jsx(Span, { className: "flex-1 truncate", children: item.label })] }));
13
+ }
14
+ function DesktopContent({ items, activeHref, collapsed, }) {
15
+ return (_jsx(Nav, { "aria-label": "User navigation", className: "flex-1 overflow-y-auto py-2", children: _jsx(Ul, { className: `space-y-0.5 ${collapsed ? "px-1" : "px-2"}`, children: items.map((item) => {
9
16
  const isActive = activeHref === item.href || activeHref.startsWith(item.href + "/");
10
- return (_jsx(Li, { children: _jsxs(Link, { href: item.href, onClick: onItemClick, className: `flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors ${isActive
11
- ? "bg-primary-50 dark:bg-primary-900/20 text-primary-600 dark:text-primary-400 font-medium"
12
- : "text-zinc-600 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-slate-800 hover:text-zinc-900 dark:hover:text-zinc-100"}`, children: [item.icon && (_jsx(Span, { className: "shrink-0 text-[1.1rem]", children: item.icon })), _jsx(Span, { className: "flex-1 truncate", children: item.label })] }) }, item.href));
17
+ return (_jsx(Li, { children: _jsx(NavLink, { item: item, isActive: isActive, collapsed: collapsed }) }, item.href));
13
18
  }) }) }));
14
19
  }
15
- export function UserSidebar({ items, mobileOpen = false, onCloseMobile, className = "", }) {
20
+ function MobileContent({ groups, items, activeHref, onItemClick, }) {
21
+ const [openGroups, setOpenGroups] = useState(() => {
22
+ if (!groups)
23
+ return {};
24
+ return Object.fromEntries(groups.map((g) => [g.title, g.defaultOpen ?? true]));
25
+ });
26
+ const toggle = useCallback((title) => setOpenGroups((prev) => ({ ...prev, [title]: !prev[title] })), []);
27
+ if (!groups || groups.length === 0) {
28
+ return (_jsx(Nav, { "aria-label": "User navigation", className: "py-2", children: _jsx(Ul, { className: "space-y-0.5 px-2", children: items.map((item) => {
29
+ const isActive = activeHref === item.href || activeHref.startsWith(item.href + "/");
30
+ return (_jsx(Li, { children: _jsx(NavLink, { item: item, isActive: isActive, onClick: onItemClick }) }, item.href));
31
+ }) }) }));
32
+ }
33
+ return (_jsx(Nav, { "aria-label": "User navigation", className: "py-2 space-y-1", children: groups.map((group) => {
34
+ const isOpen = openGroups[group.title] ?? true;
35
+ return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => toggle(group.title), className: "flex w-full items-center justify-between px-4 py-2 text-xs font-semibold uppercase tracking-wider text-zinc-400 dark:text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors", children: [_jsx("span", { children: group.title }), _jsx("span", { className: `transition-transform duration-150 text-[0.65rem] ${isOpen ? "rotate-180" : ""}`, children: "\u25BE" })] }), isOpen && (_jsx(Ul, { className: "space-y-0.5 px-2 pb-2", children: group.items.map((item) => {
36
+ const isActive = activeHref === item.href ||
37
+ activeHref.startsWith(item.href + "/");
38
+ return (_jsx(Li, { children: _jsx(NavLink, { item: item, isActive: isActive, onClick: onItemClick }) }, item.href));
39
+ }) }))] }, group.title));
40
+ }) }));
41
+ }
42
+ export function UserSidebar({ items, groups, mobileOpen = false, onCloseMobile, className = "", }) {
16
43
  const pathname = usePathname();
17
- return (_jsxs(_Fragment, { children: [_jsx(Aside, { className: `hidden md:flex w-56 shrink-0 flex-col bg-white dark:bg-slate-900 border-r border-zinc-200 dark:border-slate-700 ${className}`, children: _jsx(SidebarContent, { items: items, activeHref: pathname }) }), _jsx(BottomSheet, { open: mobileOpen, onClose: onCloseMobile ?? (() => { }), title: "My Account", children: _jsx(SidebarContent, { items: items, activeHref: pathname, onItemClick: onCloseMobile }) })] }));
44
+ const [collapsed, setCollapsed] = useState(false);
45
+ useEffect(() => {
46
+ try {
47
+ setCollapsed(localStorage.getItem(STORAGE_KEY) === "true");
48
+ }
49
+ catch {
50
+ // ignore
51
+ }
52
+ }, []);
53
+ const toggleCollapsed = useCallback(() => {
54
+ setCollapsed((prev) => {
55
+ const next = !prev;
56
+ try {
57
+ localStorage.setItem(STORAGE_KEY, String(next));
58
+ }
59
+ catch {
60
+ // ignore
61
+ }
62
+ return next;
63
+ });
64
+ }, []);
65
+ return (_jsxs(_Fragment, { children: [_jsxs(Aside, { className: `hidden md:flex flex-col bg-white dark:bg-slate-900 border-l border-zinc-200 dark:border-slate-700 shrink-0 transition-[width] duration-200 overflow-hidden ${collapsed ? "w-12" : "w-56"} ${className}`, children: [_jsx("div", { className: `flex pt-3 pb-1 ${collapsed ? "justify-center px-1" : "justify-end px-3"}`, children: _jsx("button", { type: "button", onClick: toggleCollapsed, title: collapsed ? "Expand menu" : "Collapse menu", className: "rounded-md p-1.5 text-zinc-400 hover:bg-zinc-100 dark:hover:bg-slate-800 hover:text-zinc-600 dark:hover:text-zinc-300 transition-colors text-xs leading-none", children: collapsed ? "›" : "‹" }) }), _jsx(DesktopContent, { items: items, activeHref: pathname, collapsed: collapsed })] }), _jsx(BottomSheet, { open: mobileOpen, onClose: onCloseMobile ?? (() => { }), title: "My Account", children: _jsx(MobileContent, { groups: groups, items: items, activeHref: pathname, onItemClick: onCloseMobile }) })] }));
18
66
  }
@@ -26,9 +26,16 @@ export interface AddressFormData {
26
26
  interface SetDefaultAddressData {
27
27
  addressId: string;
28
28
  }
29
+ export interface AddressFilterParams {
30
+ q?: string;
31
+ addressType?: string;
32
+ verified?: boolean;
33
+ activeOnly?: boolean;
34
+ }
29
35
  export declare function useAddresses(options?: {
30
36
  enabled?: boolean;
31
37
  listEndpoint?: string;
38
+ filters?: AddressFilterParams;
32
39
  }): import("@tanstack/react-query").UseQueryResult<Address[], Error>;
33
40
  export declare function useAddress(id: string, options?: {
34
41
  enabled?: boolean;
@@ -7,7 +7,18 @@ const DEFAULT_ENDPOINTS = {
7
7
  setDefault: ACCOUNT_ENDPOINTS.ADDRESS_SET_DEFAULT,
8
8
  };
9
9
  export function useAddresses(options) {
10
- const endpoint = options?.listEndpoint ?? DEFAULT_ENDPOINTS.list;
10
+ const sp = new URLSearchParams();
11
+ if (options?.filters?.q)
12
+ sp.set("q", options.filters.q);
13
+ if (options?.filters?.addressType)
14
+ sp.set("addressType", options.filters.addressType);
15
+ if (options?.filters?.verified)
16
+ sp.set("verified", "true");
17
+ if (options?.filters?.activeOnly)
18
+ sp.set("activeOnly", "true");
19
+ const qs = sp.toString();
20
+ const base = options?.listEndpoint ?? DEFAULT_ENDPOINTS.list;
21
+ const endpoint = qs ? `${base}?${qs}` : base;
11
22
  return useQuery({
12
23
  queryKey: ["addresses", endpoint],
13
24
  queryFn: () => apiClient.get(endpoint),
@@ -103,3 +103,15 @@ export declare function listAdminSessions(params?: {
103
103
  recentActivity: number;
104
104
  };
105
105
  }>;
106
+ export declare function listAdminNewsletterSubscribers(params?: {
107
+ filters?: string;
108
+ sorts?: string;
109
+ page?: number;
110
+ pageSize?: number;
111
+ }): Promise<import("../../..").PagedResult<import("../../..").NewsletterSubscriberDocument>>;
112
+ export declare function listAdminContactSubmissions(params?: {
113
+ filters?: string;
114
+ sorts?: string;
115
+ page?: number;
116
+ pageSize?: number;
117
+ }): Promise<import("../../..").PagedResult<import("../server").ContactSubmissionDocument>>;
@@ -11,6 +11,8 @@ import { blogRepository } from "../../blog/repository/blog.repository";
11
11
  import { storeRepository } from "../../stores/repository/store.repository";
12
12
  import { bidRepository } from "../../auctions/repository/bid.repository";
13
13
  import { payoutRepository } from "../../payments/repository/payout.repository";
14
+ import { newsletterRepository } from "../../../core/newsletter.repository";
15
+ import { contactSubmissionsRepository } from "../../../core/contact-submissions.repository";
14
16
  import { formatMonthYear } from "../../../utils";
15
17
  import { ProductStatusValues } from "../../products/schemas";
16
18
  export async function getAdminDashboardStats() {
@@ -170,3 +172,19 @@ export async function listAdminSessions(params) {
170
172
  limit: params?.limit ?? 100,
171
173
  });
172
174
  }
175
+ export async function listAdminNewsletterSubscribers(params) {
176
+ return newsletterRepository.list({
177
+ filters: params?.filters,
178
+ sorts: params?.sorts,
179
+ page: String(params?.page ?? 1),
180
+ pageSize: String(params?.pageSize ?? 50),
181
+ });
182
+ }
183
+ export async function listAdminContactSubmissions(params) {
184
+ return contactSubmissionsRepository.list({
185
+ filters: params?.filters,
186
+ sorts: params?.sorts,
187
+ page: String(params?.page ?? 1),
188
+ pageSize: String(params?.pageSize ?? 50),
189
+ });
190
+ }
@@ -7,9 +7,20 @@ import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } fr
7
7
  import { AdminListingScaffold } from "./AdminListingScaffold";
8
8
  export function AdminBlogView({ children, ...props }) {
9
9
  const hasChildren = React.Children.count(children) > 0;
10
+ const [q, setQ] = React.useState("");
11
+ const [statusFilter, setStatusFilter] = React.useState("");
12
+ const [featuredFilter, setFeaturedFilter] = React.useState("");
13
+ const filterParts = [];
14
+ if (statusFilter && statusFilter !== "All")
15
+ filterParts.push(`status==${statusFilter}`);
16
+ if (featuredFilter === "Featured Only")
17
+ filterParts.push("isFeatured==true");
18
+ const filters = filterParts.join(",") || undefined;
10
19
  const { rows, total, isLoading, errorMessage } = useAdminListingData({
11
- queryKey: ["admin", "blog", "listing"],
20
+ queryKey: ["admin", "blog", "listing", q, filters ?? ""],
12
21
  endpoint: ADMIN_ENDPOINTS.BLOG,
22
+ filters,
23
+ q,
13
24
  mapRows: (response) => toRecordArray(response.posts).map((item, index) => ({
14
25
  id: toStringValue(item.id, `post-${index}`),
15
26
  primary: toStringValue(item.title, "Untitled post"),
@@ -33,5 +44,18 @@ export function AdminBlogView({ children, ...props }) {
33
44
  if (hasChildren) {
34
45
  return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
35
46
  }
36
- return (_jsx(AdminListingScaffold, { portal: "admin", ...props, title: "Blog Publishing", subtitle: "Manage editorial drafts, featured placement, and publish readiness in the shared listing frame.", actionLabel: "New article", searchPlaceholder: "Search articles, authors, or tags", rows: rows, isLoading: isLoading, errorMessage: errorMessage, emptyLabel: "No blog posts found", resultSummary: `Showing ${rows.length} of ${total} posts` }));
47
+ return (_jsx(AdminListingScaffold, { portal: "admin", ...props, title: "Blog Publishing", subtitle: "Manage editorial drafts, featured placement, and publish readiness in the shared listing frame.", actionLabel: "New article", searchPlaceholder: "Search articles, authors, or tags", onSearch: setQ, searchValue: q, rows: rows, isLoading: isLoading, errorMessage: errorMessage, emptyLabel: "No blog posts found", resultSummary: `Showing ${rows.length} of ${total} posts`, filterGroups: [
48
+ {
49
+ title: "Status",
50
+ options: ["All", "published", "draft", "archived"],
51
+ active: statusFilter || "All",
52
+ onSelect: (opt) => setStatusFilter(opt === "All" ? "" : opt),
53
+ },
54
+ {
55
+ title: "Featured",
56
+ options: ["All", "Featured Only"],
57
+ active: featuredFilter || "All",
58
+ onSelect: (opt) => setFeaturedFilter(opt === "All" ? "" : opt),
59
+ },
60
+ ] }));
37
61
  }
@@ -7,9 +7,18 @@ import { toRecordArray, toRelativeDate, toStringValue, useAdminListingData, } fr
7
7
  import { AdminListingScaffold } from "./AdminListingScaffold";
8
8
  export function AdminCarouselView({ children, ...props }) {
9
9
  const hasChildren = React.Children.count(children) > 0;
10
+ const [q, setQ] = React.useState("");
11
+ const [statusFilter, setStatusFilter] = React.useState("");
12
+ const filterParts = [];
13
+ if (statusFilter && statusFilter !== "All") {
14
+ filterParts.push(statusFilter === "Active" ? "active==true" : "active==false");
15
+ }
16
+ const filters = filterParts.join(",") || undefined;
10
17
  const { rows, total, isLoading, errorMessage } = useAdminListingData({
11
- queryKey: ["admin", "carousel", "listing"],
18
+ queryKey: ["admin", "carousel", "listing", q, filters ?? ""],
12
19
  endpoint: `${HOMEPAGE_ENDPOINTS.CAROUSEL}?includeInactive=true`,
20
+ filters,
21
+ q,
13
22
  mapRows: (response) => {
14
23
  const sourceItems = Array.isArray(response.data)
15
24
  ? response.data
@@ -36,5 +45,12 @@ export function AdminCarouselView({ children, ...props }) {
36
45
  if (hasChildren) {
37
46
  return _jsx(ListingViewShell, { portal: "admin", ...props, children: children });
38
47
  }
39
- return (_jsx(AdminListingScaffold, { portal: "admin", ...props, title: "Homepage Carousel", subtitle: "Manage hero slide ordering, activation state, and destination links in one listing workflow.", actionLabel: "New slide", searchPlaceholder: "Search slide titles or link URLs", rows: rows, isLoading: isLoading, errorMessage: errorMessage, emptyLabel: "No carousel slides found", resultSummary: `Showing ${rows.length} of ${total} slides` }));
48
+ return (_jsx(AdminListingScaffold, { portal: "admin", ...props, title: "Homepage Carousel", subtitle: "Manage hero slide ordering, activation state, and destination links in one listing workflow.", actionLabel: "New slide", searchPlaceholder: "Search slide titles or link URLs", onSearch: setQ, searchValue: q, rows: rows, isLoading: isLoading, errorMessage: errorMessage, emptyLabel: "No carousel slides found", resultSummary: `Showing ${rows.length} of ${total} slides`, filterGroups: [
49
+ {
50
+ title: "Status",
51
+ options: ["All", "Active", "Inactive"],
52
+ active: statusFilter || "All",
53
+ onSelect: (opt) => setStatusFilter(opt === "All" ? "" : opt),
54
+ },
55
+ ] }));
40
56
  }