@mohasinac/appkit 2.7.57 → 2.7.59

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 (245) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +7 -1
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -2
  3. package/dist/_internal/server/features/scams/og.js +1 -1
  4. package/dist/_internal/shared/actions/bulk-helpers.d.ts +3 -0
  5. package/dist/_internal/shared/actions/bulk-helpers.js +19 -0
  6. package/dist/_internal/shared/config/schema.d.ts +4 -4
  7. package/dist/client.d.ts +4 -1
  8. package/dist/client.js +3 -1
  9. package/dist/configs/next.js +11 -0
  10. package/dist/configs/tailwind.d.ts +16 -3
  11. package/dist/configs/tailwind.js +18 -5
  12. package/dist/features/account/components/AddressBook.js +1 -1
  13. package/dist/features/account/components/AddressesIndexListing.js +3 -4
  14. package/dist/features/account/components/BuyerAccountGuideView.js +7 -7
  15. package/dist/features/account/components/BuyerAuctionsGuideView.js +7 -7
  16. package/dist/features/account/components/BuyerOrdersGuideView.js +6 -6
  17. package/dist/features/account/components/BuyerShoppingGuideView.js +7 -7
  18. package/dist/features/account/components/UserOffersPanel.js +1 -1
  19. package/dist/features/account/components/UserSidebar.js +14 -10
  20. package/dist/features/account/components/UserSupportView.js +4 -4
  21. package/dist/features/admin/components/AdminAdsView.js +1 -1
  22. package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -10
  23. package/dist/features/admin/components/AdminAnalyticsGuideView.js +3 -3
  24. package/dist/features/admin/components/AdminBidsView.js +3 -9
  25. package/dist/features/admin/components/AdminBlogView.js +4 -9
  26. package/dist/features/admin/components/AdminBrandEditorView.js +14 -17
  27. package/dist/features/admin/components/AdminBrandsView.js +4 -9
  28. package/dist/features/admin/components/AdminBundlesView.js +40 -59
  29. package/dist/features/admin/components/AdminCarouselView.js +8 -21
  30. package/dist/features/admin/components/AdminCartsView.js +3 -4
  31. package/dist/features/admin/components/AdminCatalogGuideView.js +5 -5
  32. package/dist/features/admin/components/AdminCategoriesView.js +4 -9
  33. package/dist/features/admin/components/AdminCategoryEditorView.js +1 -5
  34. package/dist/features/admin/components/AdminContactEditorView.js +2 -2
  35. package/dist/features/admin/components/AdminContactView.js +7 -25
  36. package/dist/features/admin/components/AdminContentGuideView.js +6 -6
  37. package/dist/features/admin/components/AdminCouponEditorView.js +14 -17
  38. package/dist/features/admin/components/AdminCouponsView.js +8 -16
  39. package/dist/features/admin/components/AdminFaqEditorView.js +14 -17
  40. package/dist/features/admin/components/AdminFaqsView.js +18 -69
  41. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -9
  42. package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
  43. package/dist/features/admin/components/AdminFeaturesView.js +1 -1
  44. package/dist/features/admin/components/AdminGuideHubView.js +1 -1
  45. package/dist/features/admin/components/AdminHistoryView.js +1 -1
  46. package/dist/features/admin/components/AdminListingScaffold.js +1 -1
  47. package/dist/features/admin/components/AdminNewsletterView.js +5 -15
  48. package/dist/features/admin/components/AdminNotificationsView.js +3 -9
  49. package/dist/features/admin/components/AdminOrdersGuideView.js +5 -5
  50. package/dist/features/admin/components/AdminOrdersView.js +3 -9
  51. package/dist/features/admin/components/AdminPayoutsView.js +3 -9
  52. package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -9
  53. package/dist/features/admin/components/AdminProductEditorView.js +1 -5
  54. package/dist/features/admin/components/AdminProductsView.js +5 -10
  55. package/dist/features/admin/components/AdminReturnRequestsView.js +1 -1
  56. package/dist/features/admin/components/AdminReviewsView.js +3 -9
  57. package/dist/features/admin/components/AdminScammerEditorView.js +3 -3
  58. package/dist/features/admin/components/AdminScammersView.js +6 -12
  59. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  60. package/dist/features/admin/components/AdminSessionsView.js +3 -9
  61. package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
  62. package/dist/features/admin/components/AdminStoreAddressesView.js +1 -1
  63. package/dist/features/admin/components/AdminStoresGuideView.js +6 -6
  64. package/dist/features/admin/components/AdminStoresView.js +3 -9
  65. package/dist/features/admin/components/AdminSublistingCategoriesView.js +3 -7
  66. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +17 -20
  67. package/dist/features/admin/components/AdminSupportTicketDetailView.js +4 -4
  68. package/dist/features/admin/components/AdminSupportTicketsView.js +9 -15
  69. package/dist/features/admin/components/AdminTeamGuideView.js +4 -4
  70. package/dist/features/admin/components/AdminTeamView.js +6 -15
  71. package/dist/features/admin/components/AdminTrustGuideView.js +5 -5
  72. package/dist/features/admin/components/AdminUserEditorView.js +1 -1
  73. package/dist/features/admin/components/AdminUsersGuideView.js +5 -5
  74. package/dist/features/admin/components/AdminUsersView.js +3 -9
  75. package/dist/features/admin/components/AdminViewCards.js +1 -1
  76. package/dist/features/admin/components/AdminWishlistsView.js +1 -1
  77. package/dist/features/admin/components/DataTable.js +1 -1
  78. package/dist/features/admin/hooks/useAdminListing.d.ts +58 -0
  79. package/dist/features/admin/hooks/useAdminListing.js +71 -0
  80. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  81. package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
  82. package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
  83. package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
  84. package/dist/features/auth/components/VerifyEmailView.js +1 -1
  85. package/dist/features/auth/schemas/firestore.d.ts +1 -0
  86. package/dist/features/blog/components/BlogIndexListing.js +3 -6
  87. package/dist/features/blog/components/BlogListView.js +1 -1
  88. package/dist/features/blog/components/BlogPostView.js +1 -1
  89. package/dist/features/cart/components/CartDrawer.js +1 -1
  90. package/dist/features/categories/components/CategoriesIndexListing.js +3 -6
  91. package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
  92. package/dist/features/checkout/components/CheckoutStepper.js +1 -1
  93. package/dist/features/collections/components/CollectionCard.js +1 -1
  94. package/dist/features/copilot/components/AdminCopilotView.js +2 -2
  95. package/dist/features/events/components/AdminEventsView.js +4 -4
  96. package/dist/features/events/components/EventPollWidget.js +2 -2
  97. package/dist/features/events/components/EventStatusBadge.js +4 -4
  98. package/dist/features/events/components/EventsIndexListing.js +3 -4
  99. package/dist/features/events/components/SpinWheelView.js +1 -1
  100. package/dist/features/faq/components/FAQAccordion.js +2 -2
  101. package/dist/features/forms/Input.js +3 -3
  102. package/dist/features/forms/Select.js +2 -2
  103. package/dist/features/forms/Textarea.js +2 -2
  104. package/dist/features/forms/utils.d.ts +1 -1
  105. package/dist/features/forms/utils.js +1 -1
  106. package/dist/features/homepage/components/AnnouncementBar.d.ts +4 -1
  107. package/dist/features/homepage/components/AnnouncementBar.js +51 -4
  108. package/dist/features/homepage/components/CharacterHotspotForm.js +2 -2
  109. package/dist/features/homepage/components/MarketplaceHomepageView.d.ts +3 -1
  110. package/dist/features/homepage/components/MarketplaceHomepageView.js +2 -2
  111. package/dist/features/homepage/components/index.d.ts +1 -1
  112. package/dist/features/homepage/components/index.js +1 -1
  113. package/dist/features/homepage/lib/section-renderer.d.ts +2 -2
  114. package/dist/features/homepage/lib/section-renderer.js +2 -2
  115. package/dist/features/layout/BottomActions.js +2 -2
  116. package/dist/features/layout/ListingLayout.js +3 -3
  117. package/dist/features/layout/TitleBarLayout.js +1 -1
  118. package/dist/features/media/index.d.ts +2 -0
  119. package/dist/features/media/index.js +1 -0
  120. package/dist/features/media/modals/ImageCropModal.js +1 -1
  121. package/dist/features/media/modals/ImageEditor.d.ts +12 -0
  122. package/dist/features/media/modals/ImageEditor.js +73 -0
  123. package/dist/features/media/upload/ImageUpload.d.ts +5 -1
  124. package/dist/features/media/upload/ImageUpload.js +33 -8
  125. package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
  126. package/dist/features/media/upload/MediaUploadField.js +26 -12
  127. package/dist/features/orders/components/OrdersList.js +7 -7
  128. package/dist/features/orders/components/RefundHistoryTable.js +2 -2
  129. package/dist/features/orders/components/RefundRequestView.js +3 -3
  130. package/dist/features/orders/repository/orders.repository.d.ts +0 -1
  131. package/dist/features/orders/repository/orders.repository.js +0 -1
  132. package/dist/features/orders/server.d.ts +1 -1
  133. package/dist/features/orders/server.js +1 -1
  134. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  135. package/dist/features/pre-orders/components/PreOrderBadge.js +4 -4
  136. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
  137. package/dist/features/pre-orders/components/PreorderCard.js +2 -2
  138. package/dist/features/products/components/CustomSectionsEditor.js +1 -1
  139. package/dist/features/products/components/GroupSettingsPanel.js +64 -48
  140. package/dist/features/products/components/MakeOfferButton.js +2 -2
  141. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
  142. package/dist/features/products/components/PrizeDrawItemsEditor.js +3 -3
  143. package/dist/features/products/components/PrizeRevealModal.js +3 -3
  144. package/dist/features/products/components/ProductDetailPageView.js +4 -4
  145. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  146. package/dist/features/products/components/ProductGrid.js +3 -3
  147. package/dist/features/products/repository/products.repository.d.ts +0 -2
  148. package/dist/features/products/repository/products.repository.js +0 -2
  149. package/dist/features/products/server.d.ts +1 -1
  150. package/dist/features/products/server.js +1 -1
  151. package/dist/features/promotions/components/CouponCard.js +7 -7
  152. package/dist/features/promotions/components/CouponsIndexListing.js +3 -2
  153. package/dist/features/promotions/components/PromotionsView.js +1 -1
  154. package/dist/features/reviews/components/ReviewDetailShell.js +2 -2
  155. package/dist/features/reviews/components/ReviewsIndexListing.js +3 -4
  156. package/dist/features/reviews/components/ReviewsList.js +1 -1
  157. package/dist/features/reviews/repository/reviews.repository.d.ts +0 -1
  158. package/dist/features/reviews/repository/reviews.repository.js +0 -1
  159. package/dist/features/reviews/server.d.ts +1 -1
  160. package/dist/features/reviews/server.js +1 -1
  161. package/dist/features/seller/components/SellerAddressesView.js +11 -21
  162. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +2 -2
  163. package/dist/features/seller/components/SellerAuctionsView.js +14 -23
  164. package/dist/features/seller/components/SellerBidsView.js +6 -6
  165. package/dist/features/seller/components/SellerBundlesView.js +13 -21
  166. package/dist/features/seller/components/SellerClassifiedView.js +14 -22
  167. package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
  168. package/dist/features/seller/components/SellerCouponsView.js +14 -20
  169. package/dist/features/seller/components/SellerDigitalCodesView.js +13 -21
  170. package/dist/features/seller/components/SellerFeaturesView.js +1 -1
  171. package/dist/features/seller/components/SellerGroupedListingsView.js +6 -10
  172. package/dist/features/seller/components/SellerLiveView.js +15 -23
  173. package/dist/features/seller/components/SellerOffersPanel.js +2 -2
  174. package/dist/features/seller/components/SellerOffersView.js +4 -5
  175. package/dist/features/seller/components/SellerOrdersView.js +9 -23
  176. package/dist/features/seller/components/SellerPayoutMethodsView.js +13 -25
  177. package/dist/features/seller/components/SellerPayoutsView.js +4 -5
  178. package/dist/features/seller/components/SellerPreOrdersView.js +13 -22
  179. package/dist/features/seller/components/SellerPrizeDrawsView.js +13 -22
  180. package/dist/features/seller/components/SellerProductsCards.js +1 -1
  181. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +1 -1
  182. package/dist/features/seller/components/SellerProductsFilterDrawer.js +3 -6
  183. package/dist/features/seller/components/SellerProductsView.js +10 -23
  184. package/dist/features/seller/components/SellerReviewsView.js +1 -1
  185. package/dist/features/seller/components/SellerShippingConfigsView.js +14 -26
  186. package/dist/features/seller/components/SellerStoreCategoriesView.js +16 -35
  187. package/dist/features/seller/components/SellerTemplatesView.js +27 -43
  188. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  189. package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
  190. package/dist/features/stores/components/StoreHeader.js +1 -1
  191. package/dist/features/stores/components/StoreListingsGuideView.js +3 -3
  192. package/dist/features/stores/components/StoreOrdersGuideView.js +4 -4
  193. package/dist/features/stores/components/StoreReviewsListing.js +3 -4
  194. package/dist/features/stores/components/StoreSettingsGuideView.js +2 -2
  195. package/dist/features/stores/components/StoresIndexListing.js +3 -4
  196. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +4 -4
  197. package/dist/features/wishlist/components/WishlistPage.js +1 -1
  198. package/dist/index.d.ts +4 -6
  199. package/dist/index.js +6 -12
  200. package/dist/react/contexts/SessionContext.d.ts +2 -0
  201. package/dist/react/contexts/SessionContext.js +2 -0
  202. package/dist/react/hooks/useEntityDelete.d.ts +15 -0
  203. package/dist/react/hooks/useEntityDelete.js +39 -0
  204. package/dist/react/index.d.ts +2 -0
  205. package/dist/react/index.js +2 -0
  206. package/dist/repositories/index.d.ts +3 -3
  207. package/dist/repositories/index.js +3 -3
  208. package/dist/styles.css +286 -3
  209. package/dist/tailwind-utilities.css +1 -1
  210. package/dist/tokens/motion.d.ts +162 -0
  211. package/dist/tokens/motion.js +89 -0
  212. package/dist/ui/DataTable.js +3 -2
  213. package/dist/ui/components/Accordion.js +2 -1
  214. package/dist/ui/components/Card.d.ts +5 -2
  215. package/dist/ui/components/Card.js +29 -11
  216. package/dist/ui/components/Div.d.ts +2 -16
  217. package/dist/ui/components/Div.js +2 -16
  218. package/dist/ui/components/Layout.d.ts +9 -19
  219. package/dist/ui/components/Layout.js +9 -7
  220. package/dist/ui/components/ListingFilterDrawer.d.ts +10 -0
  221. package/dist/ui/components/ListingFilterDrawer.js +8 -0
  222. package/dist/ui/components/Modal.js +7 -4
  223. package/dist/ui/components/Motion.d.ts +75 -0
  224. package/dist/ui/components/Motion.js +122 -0
  225. package/dist/ui/components/Semantic.d.ts +81 -14
  226. package/dist/ui/components/Semantic.js +75 -10
  227. package/dist/ui/components/Semantic.style.css +261 -2
  228. package/dist/ui/components/SideDrawer.d.ts +1 -1
  229. package/dist/ui/components/SideDrawer.js +8 -6
  230. package/dist/ui/components/SideModal.d.ts +1 -1
  231. package/dist/ui/components/SideModal.js +11 -9
  232. package/dist/ui/components/StackedViewShell.js +6 -1
  233. package/dist/ui/components/Toast.js +5 -2
  234. package/dist/ui/components/Typography.d.ts +44 -3
  235. package/dist/ui/components/Typography.js +15 -30
  236. package/dist/ui/components/Typography.style.css +24 -0
  237. package/dist/ui/components/VacationBanner.js +2 -1
  238. package/dist/ui/components/surface-tokens.d.ts +70 -0
  239. package/dist/ui/components/surface-tokens.js +68 -0
  240. package/dist/ui/forms/FormShell.d.ts +6 -1
  241. package/dist/ui/forms/FormShell.js +32 -4
  242. package/dist/ui/index.d.ts +11 -2
  243. package/dist/ui/index.js +5 -2
  244. package/dist/validation/schemas.d.ts +28 -28
  245. package/package.json +3 -1
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useMemo } from "react";
4
+ import { useEntityDelete } from "../../../react/hooks/useEntityDelete";
4
5
  import { Plus } from "lucide-react";
5
6
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
7
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
@@ -8,6 +9,7 @@ import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, FilterDrawer
8
9
  import { useBottomActions } from "../../layout";
9
10
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
10
11
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
12
+ import { buildBulkAction } from "../../../_internal/shared/actions/bulk-helpers";
11
13
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
12
14
  import { TABLE_KEYS } from "../../../constants/table-keys";
13
15
  const PAGE_SIZE = 25;
@@ -68,7 +70,13 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
68
70
  const [savingError, setSavingError] = useState(null);
69
71
  // Delete state
70
72
  const [deleteTargetId, setDeleteTargetId] = useState(null);
71
- const [deletingId, setDeletingId] = useState(null);
73
+ const { deletingId, handleDelete: performDelete } = useEntityDelete({
74
+ endpoint: SELLER_ENDPOINTS.TEMPLATE_BY_ID,
75
+ deleteFn: onDelete,
76
+ successMessage: "Template deleted.",
77
+ onSuccess: () => { refetch?.(); },
78
+ fetchOptions: { credentials: "include" },
79
+ });
72
80
  const [duplicatingId, setDuplicatingId] = useState(null);
73
81
  const { showToast } = useToast();
74
82
  const commitSearch = useCallback(() => {
@@ -184,28 +192,9 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
184
192
  }
185
193
  }, [draft, drawerMode, editingId, closeDrawer, refetch, showToast]);
186
194
  const handleDelete = useCallback(async (id) => {
187
- setDeletingId(id);
188
- try {
189
- if (onDelete) {
190
- await onDelete(id);
191
- }
192
- else {
193
- await fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
194
- method: "DELETE",
195
- credentials: "include",
196
- });
197
- }
198
- refetch?.();
199
- showToast("Template deleted.", "success");
200
- }
201
- catch (err) {
202
- showToast(err instanceof Error ? err.message : "Failed to delete template.", "error");
203
- }
204
- finally {
205
- setDeletingId(null);
206
- setDeleteTargetId(null);
207
- }
208
- }, [onDelete, refetch, showToast]);
195
+ await performDelete(id);
196
+ setDeleteTargetId(null);
197
+ }, [performDelete]);
209
198
  const handleDuplicate = useCallback(async (row) => {
210
199
  setDuplicatingId(row.id);
211
200
  try {
@@ -237,27 +226,22 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
237
226
  }
238
227
  }, [onDuplicate, refetch, showToast]);
239
228
  const bulkActions = [
240
- {
241
- id: "bulk-delete",
242
- label: ACTIONS.STORE["delete-template"].label,
243
- variant: "danger",
244
- onClick: async () => {
245
- if (onBulkDelete) {
246
- await onBulkDelete(selection.selectedIds);
247
- }
248
- else {
249
- await Promise.all(selection.selectedIds.map((id) => fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
250
- method: "DELETE",
251
- credentials: "include",
252
- })));
253
- }
254
- selection.clearSelection();
255
- refetch?.();
256
- },
257
- },
229
+ buildBulkAction(ACTIONS.STORE["delete-template"], async () => {
230
+ if (onBulkDelete) {
231
+ await onBulkDelete(selection.selectedIds);
232
+ }
233
+ else {
234
+ await Promise.all(selection.selectedIds.map((id) => fetch(SELLER_ENDPOINTS.TEMPLATE_BY_ID(id), {
235
+ method: "DELETE",
236
+ credentials: "include",
237
+ })));
238
+ }
239
+ selection.clearSelection();
240
+ refetch?.();
241
+ }),
258
242
  ];
259
243
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
260
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-4 py-3 text-sm text-red-700 dark:text-red-200", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
244
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
261
245
  ? "No templates match your search or filters"
262
246
  : "No templates yet — add your first product template" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: pageRows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
263
247
  {
@@ -275,5 +259,5 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
275
259
  onClick: () => setDeleteTargetId(row.id),
276
260
  disabled: deletingId === row.id,
277
261
  },
278
- ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-3 py-2 text-sm text-red-700 dark:text-red-200", children: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
262
+ ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-error-surface dark:border-red-900/60 px-3 py-2 text-sm text-error", children: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
279
263
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Div, Heading, Span, Text } from "../../../../ui";
3
3
  export function SellerTopProducts({ products, labels = {}, formatRevenue = (amount) => String(amount), renderProductLink, renderEmptyAction, className = "", }) {
4
- return (_jsxs(Div, { className: `bg-white dark:bg-neutral-900 rounded-xl border border-neutral-200 dark:border-neutral-800 p-4 sm:p-6 ${className}`, children: [labels.title && (_jsx(Heading, { level: 3, className: "text-base font-semibold mb-4", children: labels.title })), products.length > 0 ? (_jsx(Div, { className: "divide-y divide-neutral-100 dark:divide-neutral-800", children: products.map((product, index) => (_jsxs(Div, { className: "flex items-center gap-4 py-3", children: [_jsxs(Span, { className: "w-6 text-sm font-bold text-neutral-500 dark:text-neutral-400", children: [index + 1, "."] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "text-sm font-medium truncate", children: product.title }), _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-neutral-400", children: [product.orders, " ", labels.ordersLabel ?? "orders"] })] }), _jsxs(Div, { className: "text-right ml-2", children: [_jsx(Span, { className: "text-sm font-semibold text-emerald-600 dark:text-emerald-400", children: formatRevenue(product.revenue) }), renderProductLink?.(product)] })] }, product.productId))) })) : (_jsxs(Div, { className: "text-center py-8", children: [_jsx(Text, { className: "text-sm font-medium", children: labels.noData ?? "No data available" }), labels.noDataDescription && (_jsx(Text, { className: "text-xs text-neutral-500 dark:text-neutral-400 mt-1", children: labels.noDataDescription })), renderEmptyAction?.()] }))] }));
4
+ return (_jsxs(Div, { className: `bg-white dark:bg-neutral-900 rounded-xl border border-neutral-200 dark:border-neutral-800 p-4 sm:p-6 ${className}`, children: [labels.title && (_jsx(Heading, { level: 3, className: "text-base font-semibold mb-4", children: labels.title })), products.length > 0 ? (_jsx(Div, { className: "divide-y divide-neutral-100 dark:divide-neutral-800", children: products.map((product, index) => (_jsxs(Div, { className: "flex items-center gap-4 py-3", children: [_jsxs(Span, { className: "w-6 text-sm font-bold text-neutral-500 dark:text-neutral-400", children: [index + 1, "."] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "text-sm font-medium truncate", children: product.title }), _jsxs(Text, { className: "text-xs text-neutral-500 dark:text-neutral-400", children: [product.orders, " ", labels.ordersLabel ?? "orders"] })] }), _jsxs(Div, { className: "text-right ml-2", children: [_jsx(Span, { className: "text-sm font-semibold text-success", children: formatRevenue(product.revenue) }), renderProductLink?.(product)] })] }, product.productId))) })) : (_jsxs(Div, { className: "text-center py-8", children: [_jsx(Text, { className: "text-sm font-medium", children: labels.noData ?? "No data available" }), labels.noDataDescription && (_jsx(Text, { className: "text-xs text-neutral-500 dark:text-neutral-400 mt-1", children: labels.noDataDescription })), renderEmptyAction?.()] }))] }));
5
5
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowLeft } from "lucide-react";
3
- import { Alert, Div, Heading, Section, Text } from "../../../ui";
3
+ import { Alert, Div, Heading, Section, Span, Text } from "../../../ui";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
5
  const SUBHEADING = "mb-1 font-semibold text-[var(--appkit-color-text)]";
6
6
  const LIST_DISC = "list-disc leading-relaxed";
@@ -64,7 +64,7 @@ const COUPON_FIELDS = [
64
64
  },
65
65
  ];
66
66
  function CouponsSection() {
67
- return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Admin coupons vs store coupons" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsxs("li", { className: LIST_DISC, children: [_jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "Admin coupons" }), " \u2014 created by LetItRip and apply platform-wide (all stores). You cannot create these."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "Store coupons" }), " \u2014 created by you. Apply only to purchases from your store. You control the terms."] }), _jsx("li", { className: LIST_DISC, children: "Admin coupons and store coupons can stack if the admin coupon has \"Combine with seller coupons\" enabled. If not, only the better coupon is applied automatically." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Coupon field reference" }), _jsx(Div, { className: "space-y-3", children: COUPON_FIELDS.map(({ field, detail }) => (_jsxs(Div, { className: "flex gap-3", children: [_jsx(Text, { className: "shrink-0 w-32 font-semibold text-[var(--appkit-color-text)] text-sm", children: field }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)] text-sm leading-relaxed", children: detail })] }, field))) })] })] }));
67
+ return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Admin coupons vs store coupons" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsxs("li", { className: LIST_DISC, children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Admin coupons" }), " \u2014 created by LetItRip and apply platform-wide (all stores). You cannot create these."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Store coupons" }), " \u2014 created by you. Apply only to purchases from your store. You control the terms."] }), _jsx("li", { className: LIST_DISC, children: "Admin coupons and store coupons can stack if the admin coupon has \"Combine with seller coupons\" enabled. If not, only the better coupon is applied automatically." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Coupon field reference" }), _jsx(Div, { className: "space-y-3", children: COUPON_FIELDS.map(({ field, detail }) => (_jsxs(Div, { className: "flex gap-3", children: [_jsx(Text, { className: "shrink-0 w-32 font-semibold text-[var(--appkit-color-text)] text-sm", children: field }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)] text-sm leading-relaxed", children: detail })] }, field))) })] })] }));
68
68
  }
69
69
  // -- Section 4: Promoted & featured listings ----------------------------------
70
70
  function PromotedSection() {
@@ -3,7 +3,7 @@ import { Button, Div, Heading, RichText, Row, Section, Span, Text, } from "../..
3
3
  import { normalizeRichTextHtml } from "../../../utils/string.formatter";
4
4
  import { ShareButton } from "../../products/components/ShareButton";
5
5
  export function StoreHeader({ store, labels = {}, onFollow, className = "", }) {
6
- return (_jsxs(Section, { className: `bg-white dark:bg-slate-900 border-b border-gray-200 dark:border-slate-700 ${className}`, children: [store.storeBannerURL && (_jsx(Div, { className: "h-40 md:h-56 overflow-hidden bg-gray-100 dark:bg-slate-800", children: _jsx(Div, { role: "img", "aria-label": `${store.storeName} banner`, className: "h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${store.storeBannerURL})` } }) })), _jsxs(Div, { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4", children: [_jsxs(Div, { className: "flex items-end gap-4", children: [store.storeLogoURL ? (_jsx(Div, { role: "img", "aria-label": store.storeName, className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-center bg-cover shadow-sm", style: { backgroundImage: `url(${store.storeLogoURL})` } })) : (_jsx(Div, { className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center text-orange-600 dark:text-orange-400 font-bold text-2xl shadow-sm", children: store.storeName[0]?.toUpperCase() })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Div, { className: "flex flex-wrap items-center gap-2 mb-0.5", children: [_jsx(Heading, { level: 1, className: "text-xl font-bold text-gray-900 dark:text-zinc-100", children: store.storeName }), store.averageRating != null && store.averageRating > 0 && (_jsxs(Span, { className: "inline-flex items-center gap-1 text-sm font-medium text-amber-500", children: ["\u2605 ", store.averageRating.toFixed(1)] }))] }), _jsxs(Row, { className: "gap-3 text-xs text-gray-500 dark:text-zinc-400 mb-0.5", children: [store.category && _jsx(Span, { className: "capitalize", children: store.category }), store.totalProducts != null && store.totalProducts > 0 && (_jsxs(Span, { children: [store.totalProducts, " ", labels.products ?? "products"] })), store.totalReviews != null && store.totalReviews > 0 && (_jsxs(Span, { children: [store.totalReviews, " ", labels.reviews ?? "reviews"] })), store.itemsSold != null && store.itemsSold > 0 && (_jsxs(Span, { children: [store.itemsSold, " ", labels.sold ?? "sold"] }))] }), store.storeDescription && (_jsx(RichText, { html: normalizeRichTextHtml(store.storeDescription), copyableCode: true, className: "mt-0.5" }))] }), _jsxs(Row, { gap: "sm", align: "center", className: "shrink-0", children: [_jsx(ShareButton, { title: store.storeName }), onFollow && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onFollow(store.storeSlug), className: "rounded-lg border border-orange-500 px-4 py-2 text-sm font-medium text-orange-500 hover:bg-orange-50 transition-colors", children: labels.follow ?? "Follow" }))] })] }), store.isVacationMode && (_jsx(Text, { className: "mt-3 rounded-lg bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 px-3 py-2 text-sm text-yellow-700 dark:text-yellow-300", children: store.vacationMessage ??
6
+ return (_jsxs(Section, { surface: "default", className: `border-b border-gray-200 dark:border-slate-700 ${className}`, children: [store.storeBannerURL && (_jsx(Div, { className: "h-40 md:h-56 overflow-hidden bg-gray-100 dark:bg-slate-800", children: _jsx(Div, { role: "img", "aria-label": `${store.storeName} banner`, className: "h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${store.storeBannerURL})` } }) })), _jsxs(Div, { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4", children: [_jsxs(Div, { className: "flex items-end gap-4", children: [store.storeLogoURL ? (_jsx(Div, { role: "img", "aria-label": store.storeName, className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-center bg-cover shadow-sm", style: { backgroundImage: `url(${store.storeLogoURL})` } })) : (_jsx(Div, { className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center text-orange-600 dark:text-orange-400 font-bold text-2xl shadow-sm", children: store.storeName[0]?.toUpperCase() })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Div, { className: "flex flex-wrap items-center gap-2 mb-0.5", children: [_jsx(Heading, { level: 1, className: "text-xl font-bold text-gray-900 dark:text-zinc-100", children: store.storeName }), store.averageRating != null && store.averageRating > 0 && (_jsxs(Span, { className: "inline-flex items-center gap-1 text-sm font-medium text-amber-500", children: ["\u2605 ", store.averageRating.toFixed(1)] }))] }), _jsxs(Row, { className: "gap-3 text-xs text-gray-500 dark:text-zinc-400 mb-0.5", children: [store.category && _jsx(Span, { className: "capitalize", children: store.category }), store.totalProducts != null && store.totalProducts > 0 && (_jsxs(Span, { children: [store.totalProducts, " ", labels.products ?? "products"] })), store.totalReviews != null && store.totalReviews > 0 && (_jsxs(Span, { children: [store.totalReviews, " ", labels.reviews ?? "reviews"] })), store.itemsSold != null && store.itemsSold > 0 && (_jsxs(Span, { children: [store.itemsSold, " ", labels.sold ?? "sold"] }))] }), store.storeDescription && (_jsx(RichText, { html: normalizeRichTextHtml(store.storeDescription), copyableCode: true, className: "mt-0.5" }))] }), _jsxs(Row, { gap: "sm", align: "center", className: "shrink-0", children: [_jsx(ShareButton, { title: store.storeName }), onFollow && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onFollow(store.storeSlug), className: "rounded-lg border border-orange-500 px-4 py-2 text-sm font-medium text-orange-500 hover:bg-orange-50 transition-colors", children: labels.follow ?? "Follow" }))] })] }), store.isVacationMode && (_jsx(Text, { className: "mt-3 rounded-lg bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 px-3 py-2 text-sm text-yellow-700 dark:text-yellow-300", children: store.vacationMessage ??
7
7
  labels.vacationMode ??
8
8
  "Store is on vacation mode" }))] })] }));
9
9
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowLeft } from "lucide-react";
3
- import { Alert, Div, Heading, Section, Text } from "../../../ui";
3
+ import { Alert, Div, Heading, Section, Span, Text } from "../../../ui";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
5
  const SUBHEADING = "mb-1 font-semibold text-[var(--appkit-color-text)]";
6
6
  const LIST_DISC = "list-disc leading-relaxed";
@@ -91,7 +91,7 @@ function StandardWalkthrough() {
91
91
  }
92
92
  // -- Section 3: Auction walkthrough --------------------------------------------
93
93
  function AuctionWalkthrough() {
94
- return (_jsxs(Div, { className: "space-y-4 text-sm text-[var(--appkit-color-text-muted)]", children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Reserve price vs starting bid" }), _jsxs(Text, { className: "leading-relaxed", children: ["The ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "starting bid" }), " is the minimum first bid a buyer can place. The ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "reserve price" }), " is the minimum price you are willing to accept \u2014 if bidding does not reach the reserve, you are not obligated to sell. The reserve is hidden from buyers."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Bid increment" }), _jsx(Div, { className: "overflow-x-auto", children: _jsxs("table", { className: "text-xs min-w-[320px]", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-[var(--appkit-color-border)]", children: [_jsx("th", { className: "py-2 pr-4 text-left font-semibold text-[var(--appkit-color-text)]", children: "Current high bid" }), _jsx("th", { className: "py-2 text-left font-semibold text-[var(--appkit-color-text)]", children: "Minimum increment" })] }) }), _jsx("tbody", { className: "divide-y divide-[var(--appkit-color-border)]", children: [
94
+ return (_jsxs(Div, { className: "space-y-4 text-sm text-[var(--appkit-color-text-muted)]", children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Reserve price vs starting bid" }), _jsxs(Text, { className: "leading-relaxed", children: ["The ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "starting bid" }), " is the minimum first bid a buyer can place. The ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "reserve price" }), " is the minimum price you are willing to accept \u2014 if bidding does not reach the reserve, you are not obligated to sell. The reserve is hidden from buyers."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Bid increment" }), _jsx(Div, { className: "overflow-x-auto", children: _jsxs("table", { className: "text-xs min-w-[320px]", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-[var(--appkit-color-border)]", children: [_jsx("th", { className: "py-2 pr-4 text-left font-semibold text-[var(--appkit-color-text)]", children: "Current high bid" }), _jsx("th", { className: "py-2 text-left font-semibold text-[var(--appkit-color-text)]", children: "Minimum increment" })] }) }), _jsx("tbody", { className: "divide-y divide-[var(--appkit-color-border)]", children: [
95
95
  ["₹0 – ₹499", "₹10"],
96
96
  ["₹500 – ₹1,999", "₹25"],
97
97
  ["₹2,000 – ₹9,999", "₹100"],
@@ -101,7 +101,7 @@ function AuctionWalkthrough() {
101
101
  }
102
102
  // -- Section 4: Pre-order walkthrough ------------------------------------------
103
103
  function PreorderWalkthrough() {
104
- return (_jsxs(Div, { className: "space-y-4 text-sm text-[var(--appkit-color-text-muted)]", children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Deposit mechanic" }), _jsxs(Text, { className: "leading-relaxed", children: ["Set a ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "deposit percentage" }), " (e.g. 20%). Buyers pay the deposit at checkout. The balance is collected when the item arrives and you mark the pre-order ready. Buyers see both amounts clearly on the checkout page."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Expected delivery date" }), _jsx(Text, { className: "leading-relaxed", children: "Set a realistic estimate. Buyers rely on this to decide whether to pre-order. You can update the date later, but repeated delays hurt your store rating." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "\"Confirmed supplier\" requirement" }), _jsx(Text, { className: "leading-relaxed", children: "Only list pre-orders for items you have confirmed supply for \u2014 e.g. you have placed a purchase order with a distributor or manufacturer. Speculative pre-orders without supplier confirmation violate platform rules and may result in store suspension." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Cancellation rules" }), _jsx(Text, { className: "leading-relaxed", children: "Buyers can cancel a pre-order within 24 hours of placing it. After 24 hours, cancellation requires seller approval. If you cannot fulfill the pre-order, initiate cancellation promptly \u2014 the deposit is refunded automatically." })] })] }));
104
+ return (_jsxs(Div, { className: "space-y-4 text-sm text-[var(--appkit-color-text-muted)]", children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Deposit mechanic" }), _jsxs(Text, { className: "leading-relaxed", children: ["Set a ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "deposit percentage" }), " (e.g. 20%). Buyers pay the deposit at checkout. The balance is collected when the item arrives and you mark the pre-order ready. Buyers see both amounts clearly on the checkout page."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Expected delivery date" }), _jsx(Text, { className: "leading-relaxed", children: "Set a realistic estimate. Buyers rely on this to decide whether to pre-order. You can update the date later, but repeated delays hurt your store rating." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "\"Confirmed supplier\" requirement" }), _jsx(Text, { className: "leading-relaxed", children: "Only list pre-orders for items you have confirmed supply for \u2014 e.g. you have placed a purchase order with a distributor or manufacturer. Speculative pre-orders without supplier confirmation violate platform rules and may result in store suspension." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Cancellation rules" }), _jsx(Text, { className: "leading-relaxed", children: "Buyers can cancel a pre-order within 24 hours of placing it. After 24 hours, cancellation requires seller approval. If you cannot fulfill the pre-order, initiate cancellation promptly \u2014 the deposit is refunded automatically." })] })] }));
105
105
  }
106
106
  // -- Section 5: Product status lifecycle ---------------------------------------
107
107
  const STATUS_LIFECYCLE = `
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowLeft } from "lucide-react";
3
- import { Accordion, Alert, Div, Heading, Section, Text } from "../../../ui";
3
+ import { Accordion, Alert, Div, Heading, Section, Span, Text } from "../../../ui";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
5
  const SUBHEADING = "mb-1 font-semibold text-[var(--appkit-color-text)]";
6
6
  const LIST_DISC = "list-disc leading-relaxed";
@@ -85,15 +85,15 @@ function CarriersSection() {
85
85
  }
86
86
  // -- Section 4: Cancellations -------------------------------------------------
87
87
  function CancellationsSection() {
88
- return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Who can cancel" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsxs("li", { className: LIST_DISC, children: [_jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "Buyer" }), " \u2014 can self-cancel any time before the order reaches SHIPPED status."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "Seller (you)" }), " \u2014 can cancel any time before SHIPPED (e.g. item found damaged during packaging)."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "LetItRip admin" }), " \u2014 can force-cancel at any status for policy violations or unresolved disputes."] })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Refund timeline" }), _jsxs(Text, { className: "leading-relaxed", children: ["Cancellation triggers an automatic Razorpay refund. Funds typically reach the buyer in", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: " 3\u20137 business days" }), " depending on the payment method (UPI is usually 1\u20132 business days)."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Already shipped?" }), _jsx(Text, { className: "leading-relaxed", children: "If you have already dispatched the item but the order is still PROCESSING (tracking not yet entered), enter the tracking number and mark it SHIPPED first \u2014 then contact the buyer via order notes. Do not cancel after shipping; work with the buyer to return the item through the normal return flow." })] }), _jsx(Alert, { variant: "warning", title: "Repeated cancellations affect your rating", children: "Cancelling more than 5% of your orders per month will reduce your store rating and may result in listing restrictions. Only cancel if you genuinely cannot fulfil \u2014 never as a price-change workaround." })] }));
88
+ return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Who can cancel" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsxs("li", { className: LIST_DISC, children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Buyer" }), " \u2014 can self-cancel any time before the order reaches SHIPPED status."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "Seller (you)" }), " \u2014 can cancel any time before SHIPPED (e.g. item found damaged during packaging)."] }), _jsxs("li", { className: LIST_DISC, children: [_jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "LetItRip admin" }), " \u2014 can force-cancel at any status for policy violations or unresolved disputes."] })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Refund timeline" }), _jsxs(Text, { className: "leading-relaxed", children: ["Cancellation triggers an automatic Razorpay refund. Funds typically reach the buyer in", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: " 3\u20137 business days" }), " depending on the payment method (UPI is usually 1\u20132 business days)."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Already shipped?" }), _jsx(Text, { className: "leading-relaxed", children: "If you have already dispatched the item but the order is still PROCESSING (tracking not yet entered), enter the tracking number and mark it SHIPPED first \u2014 then contact the buyer via order notes. Do not cancel after shipping; work with the buyer to return the item through the normal return flow." })] }), _jsx(Alert, { variant: "warning", title: "Repeated cancellations affect your rating", children: "Cancelling more than 5% of your orders per month will reduce your store rating and may result in listing restrictions. Only cancel if you genuinely cannot fulfil \u2014 never as a price-change workaround." })] }));
89
89
  }
90
90
  // -- Section 5: Return requests -----------------------------------------------
91
91
  function ReturnsSection() {
92
- return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "When a buyer can raise a return" }), _jsxs(Text, { className: "leading-relaxed", children: ["Buyers can open a return request within the ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "return window" }), " after the order is marked DELIVERED. The default return window is 7 days. Stores with the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "extended_return_window" }), " capability can offer 30 days."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "What you see" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "The buyer's reason for return (pre-defined category + optional description)." }), _jsx("li", { className: LIST_DISC, children: "Photos of the item as received." }), _jsx("li", { className: LIST_DISC, children: "A 3-day SLA to respond before LetItRip mediates." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Accepting a return" }), _jsx(Text, { className: "leading-relaxed", children: "Click \"Accept return\" in the order detail. The buyer will receive a return shipping label or instructions. Once the item is received by you and you confirm it, the refund is triggered automatically via Razorpay. The payout for this order is withheld." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Rejecting a return" }), _jsx(Text, { className: "leading-relaxed", children: "You can reject a return request with a reason. If the buyer disagrees, they can escalate to LetItRip support. LetItRip will mediate \u2014 if the evidence supports the buyer, the return will be approved regardless of your rejection. Unjustified rejections count against your seller rating." })] })] }));
92
+ return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "When a buyer can raise a return" }), _jsxs(Text, { className: "leading-relaxed", children: ["Buyers can open a return request within the ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "return window" }), " after the order is marked DELIVERED. The default return window is 7 days. Stores with the ", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded", children: "extended_return_window" }), " capability can offer 30 days."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "What you see" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "The buyer's reason for return (pre-defined category + optional description)." }), _jsx("li", { className: LIST_DISC, children: "Photos of the item as received." }), _jsx("li", { className: LIST_DISC, children: "A 3-day SLA to respond before LetItRip mediates." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Accepting a return" }), _jsx(Text, { className: "leading-relaxed", children: "Click \"Accept return\" in the order detail. The buyer will receive a return shipping label or instructions. Once the item is received by you and you confirm it, the refund is triggered automatically via Razorpay. The payout for this order is withheld." })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Rejecting a return" }), _jsx(Text, { className: "leading-relaxed", children: "You can reject a return request with a reason. If the buyer disagrees, they can escalate to LetItRip support. LetItRip will mediate \u2014 if the evidence supports the buyer, the return will be approved regardless of your rejection. Unjustified rejections count against your seller rating." })] })] }));
93
93
  }
94
94
  // -- Section 6: Auction orders ------------------------------------------------
95
95
  function AuctionOrdersSection() {
96
- return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Payment window" }), _jsxs(Text, { className: "leading-relaxed", children: ["Auction winners have ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "48 hours" }), " from auction end to complete payment. You will receive a notification when the auction closes and again when the winner pays."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "If the winner does not pay" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "The order is automatically cancelled after 48 hours." }), _jsx("li", { className: LIST_DISC, children: "You are notified. The winner may receive a bid restriction on their account." }), _jsx("li", { className: LIST_DISC, children: "If \"offer to next bidder\" is enabled in your auction settings, the next-highest bidder is contacted automatically." }), _jsx("li", { className: LIST_DISC, children: "You can re-list the item immediately." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Fulfilment after payment" }), _jsx(Text, { className: "leading-relaxed", children: "Once the auction order is paid, it enters PENDING status \u2014 the same fulfilment flow as a standard order applies. Process and ship within your stated dispatch time." })] }), _jsx(Alert, { variant: "info", title: "Auction orders cannot be cancelled by the buyer", children: "Unlike standard orders, auction orders cannot be self-cancelled by the buyer after payment. If a buyer requests a cancel, it requires seller approval. Treat winning bids as binding commitments." })] }));
96
+ return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Payment window" }), _jsxs(Text, { className: "leading-relaxed", children: ["Auction winners have ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "48 hours" }), " from auction end to complete payment. You will receive a notification when the auction closes and again when the winner pays."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "If the winner does not pay" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "The order is automatically cancelled after 48 hours." }), _jsx("li", { className: LIST_DISC, children: "You are notified. The winner may receive a bid restriction on their account." }), _jsx("li", { className: LIST_DISC, children: "If \"offer to next bidder\" is enabled in your auction settings, the next-highest bidder is contacted automatically." }), _jsx("li", { className: LIST_DISC, children: "You can re-list the item immediately." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Fulfilment after payment" }), _jsx(Text, { className: "leading-relaxed", children: "Once the auction order is paid, it enters PENDING status \u2014 the same fulfilment flow as a standard order applies. Process and ship within your stated dispatch time." })] }), _jsx(Alert, { variant: "info", title: "Auction orders cannot be cancelled by the buyer", children: "Unlike standard orders, auction orders cannot be self-cancelled by the buyer after payment. If a buyer requests a cancel, it requires seller approval. Treat winning bids as binding commitments." })] }));
97
97
  }
98
98
  // -- Section 7: Common questions (FAQ collapsibles) ----------------------------
99
99
  const FAQS = [
@@ -1,9 +1,8 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useMemo } from "react";
4
- import { X } from "lucide-react";
5
4
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
- import { ListingToolbar, Pagination, Row, Span, Text } from "../../../ui";
5
+ import { ListingFilterDrawer, ListingToolbar, Pagination, Row, Span, Text } from "../../../ui";
7
6
  import { ReviewCard } from "../../reviews/components/ReviewsList";
8
7
  import { ReviewFilters, REVIEW_PUBLIC_SORT_OPTIONS } from "../../reviews/components/ReviewFilters";
9
8
  import { useStoreReviews } from "../hooks/useStores";
@@ -102,5 +101,5 @@ export function StoreReviewsListing({ storeSlug }) {
102
101
  value: opt.value,
103
102
  label: SORT_OPTION_LABELS[opt.key] ?? opt.key,
104
103
  }));
105
- return (_jsxs("div", { className: "min-h-screen", children: [totalReviews > 0 && (_jsxs(Row, { align: "center", gap: "sm", className: "px-4 py-3 border-b border-zinc-200 dark:border-slate-700", children: [_jsx(Span, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-100", children: averageRating.toFixed(1) }), _jsxs(Span, { className: "text-zinc-500 dark:text-zinc-400 text-sm", children: ["/ 5 \u00B7 ", totalReviews, " reviews"] })] })), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search reviews...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: sortOptions, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6 px-4", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: Array.from({ length: 6 }).map((_, i) => (_jsx("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: _jsxs("div", { className: "p-4 space-y-3", children: [_jsx("div", { className: "h-4 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-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" })] }) }, i))) })) : reviews.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No reviews found." })) : view === "list" ? (_jsx("div", { className: "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800", children: reviews.map((review) => (_jsx(ReviewCard, { review: review, context: "store" }, review.id))) })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: reviews.map((review) => (_jsx(ReviewCard, { review: review, context: "store" }, review.id))) })) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _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: [_jsx("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Filters" }), _jsxs("div", { className: "flex items-center gap-2", children: [activeFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-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(ReviewFilters, { table: pendingTable, variant: "public" }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", activeFilterCount > 0 ? ` (${activeFilterCount})` : ""] }) })] })] }))] }));
104
+ return (_jsxs("div", { className: "min-h-screen", children: [totalReviews > 0 && (_jsxs(Row, { align: "center", gap: "sm", className: "px-4 py-3 border-b border-zinc-200 dark:border-slate-700", children: [_jsx(Span, { className: "text-2xl font-bold text-zinc-900 dark:text-zinc-100", children: averageRating.toFixed(1) }), _jsxs(Span, { className: "text-zinc-500 dark:text-zinc-400 text-sm", children: ["/ 5 \u00B7 ", totalReviews, " reviews"] })] })), _jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search reviews...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: sortOptions, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6 px-4", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: Array.from({ length: 6 }).map((_, i) => (_jsx("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: _jsxs("div", { className: "p-4 space-y-3", children: [_jsx("div", { className: "h-4 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-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" })] }) }, i))) })) : reviews.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No reviews found." })) : view === "list" ? (_jsx("div", { className: "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800", children: reviews.map((review) => (_jsx(ReviewCard, { review: review, context: "store" }, review.id))) })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: reviews.map((review) => (_jsx(ReviewCard, { review: review, context: "store" }, review.id))) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(ReviewFilters, { table: pendingTable, variant: "public" }) })] }));
106
105
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowLeft } from "lucide-react";
3
- import { Alert, Div, Heading, Section, Text } from "../../../ui";
3
+ import { Alert, Div, Heading, Section, Span, Text } from "../../../ui";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
5
  const SUBHEADING = "mb-1 font-semibold text-[var(--appkit-color-text)]";
6
6
  const LIST_DISC = "list-disc leading-relaxed";
@@ -19,7 +19,7 @@ function ShippingSection() {
19
19
  }
20
20
  // -- Section 3: Return policy -------------------------------------------------
21
21
  function ReturnPolicySection() {
22
- return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Store-level return window" }), _jsxs(Text, { className: "leading-relaxed", children: ["The default return window is ", _jsx("strong", { className: "text-[var(--appkit-color-text)]", children: "7 days" }), " from the DELIVERED date. Stores with the", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded mx-1", children: "extended_return_window" }), "capability can offer 30 days. The return window is displayed on every product detail page in the Returns tab."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Non-returnable categories" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "Opened card packs (boosters, elite trainer boxes)." }), _jsx("li", { className: LIST_DISC, children: "Cracked or opened graded slabs \u2014 unless the defect was documented before shipping." }), _jsx("li", { className: LIST_DISC, children: "Items explicitly marked \"Final Sale\" in the listing." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "What buyers see" }), _jsx(Text, { className: "leading-relaxed", children: "Buyers see the return window and non-returnable note in the product detail page Returns tab before purchasing. This cannot be suppressed \u2014 it is platform policy to always show return terms." })] })] }));
22
+ return (_jsxs(Div, { className: SECTION_BODY, children: [_jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Store-level return window" }), _jsxs(Text, { className: "leading-relaxed", children: ["The default return window is ", _jsx(Span, { weight: "bold", className: "text-[var(--appkit-color-text)]", children: "7 days" }), " from the DELIVERED date. Stores with the", _jsx("code", { className: "text-xs bg-[var(--appkit-color-border)] px-1 rounded mx-1", children: "extended_return_window" }), "capability can offer 30 days. The return window is displayed on every product detail page in the Returns tab."] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "Non-returnable categories" }), _jsxs("ul", { className: "space-y-1 pl-5", children: [_jsx("li", { className: LIST_DISC, children: "Opened card packs (boosters, elite trainer boxes)." }), _jsx("li", { className: LIST_DISC, children: "Cracked or opened graded slabs \u2014 unless the defect was documented before shipping." }), _jsx("li", { className: LIST_DISC, children: "Items explicitly marked \"Final Sale\" in the listing." })] })] }), _jsxs(Div, { children: [_jsx(Text, { className: SUBHEADING, children: "What buyers see" }), _jsx(Text, { className: "leading-relaxed", children: "Buyers see the return window and non-returnable note in the product detail page Returns tab before purchasing. This cannot be suppressed \u2014 it is platform policy to always show return terms." })] })] }));
23
23
  }
24
24
  // -- Section 4: Vacation mode -------------------------------------------------
25
25
  function VacationModeSection() {
@@ -1,10 +1,9 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useMemo } from "react";
4
- import { SlidersHorizontal, X } from "lucide-react";
5
4
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
5
  import { useStores } from "../hooks/useStores";
7
- import { BulkActionBar, ListingToolbar, Pagination, Text } from "../../../ui";
6
+ import { BulkActionBar, ListingFilterDrawer, ListingToolbar, Pagination, Text } from "../../../ui";
8
7
  import { ROUTES } from "../../../next";
9
8
  import { InteractiveStoreCard } from "./InteractiveStoreCard";
10
9
  import { StoreFilters } from "./StoreFilters";
@@ -150,5 +149,5 @@ export function StoresIndexListing({ initialData }) {
150
149
  },
151
150
  ] } } : {});
152
151
  return (_jsx(InteractiveStoreCard, { store: store, href: String(ROUTES.PUBLIC.STORE_DETAIL(storeKey)), selectable: selection.isSelecting, isSelected: selection.isSelected(store.id ?? store.storeSlug), onSelect: (id, sel) => { void sel; selection.toggle(id); } }, storeKey));
153
- }) })) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _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"] }), _jsxs("div", { className: "flex items-center gap-2", children: [pendingFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-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(StoreFilters, { table: pendingTable }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", pendingFilterCount > 0 ? ` (${pendingFilterCount})` : ""] }) })] })] }))] }));
152
+ }) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: pendingFilterCount, children: _jsx(StoreFilters, { table: pendingTable }) })] }));
154
153
  }
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  const CLS_SECTION_CARD = "border border-zinc-200 dark:border-zinc-700 rounded-xl p-5";
5
5
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6
- import { Alert, Badge, Button, Div, Form, FormActions, Heading, Input, Row, Section, Stack, Text, Toggle, useToast } from "../../../ui";
6
+ import { Alert, Badge, Button, Div, Form, FormActions, Heading, Input, Row, Section, Span, Stack, Text, Toggle, useToast } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
8
  import { WHATSAPP_SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
9
9
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
@@ -157,13 +157,13 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
157
157
  }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Connection" }), isLoading ? null : cfg?.connected ? (_jsx(Badge, { variant: "success", children: "Connected" })) : (_jsx(Badge, { variant: "default", children: "Not configured" }))] }), _jsxs(Form, { onSubmit: (e) => {
158
158
  e.preventDefault();
159
159
  saveMutation.mutate();
160
- }, className: "space-y-4", children: [_jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-4", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: "Enable catalog sync" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { gap: "sm", align: "center", className: "text-xs text-zinc-500 dark:text-zinc-400 mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mb-3", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Div, { className: "flex gap-3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => importMutation.mutate(), isLoading: importMutation.isPending, disabled: !cfg?.connected || !syncEnabled || importMutation.isPending, variant: "secondary", children: importMutation.isPending ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mt-3", children: [_jsx("strong", { children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx("strong", { children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-2", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-3", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { className: "bg-zinc-50 dark:bg-zinc-800/60 rounded-lg px-4 py-3 text-sm text-zinc-700 dark:text-zinc-200 font-mono", children: buildPurchaseAnnouncementMessage({
160
+ }, className: "space-y-4", children: [_jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-4", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: "Enable catalog sync" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { gap: "sm", align: "center", className: "text-xs text-zinc-500 dark:text-zinc-400 mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mb-3", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Div, { className: "flex gap-3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => importMutation.mutate(), isLoading: importMutation.isPending, disabled: !cfg?.connected || !syncEnabled || importMutation.isPending, variant: "secondary", children: importMutation.isPending ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 mt-3", children: [_jsx(Span, { weight: "bold", children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx(Span, { weight: "bold", children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-2", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-3", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { className: "bg-zinc-50 dark:bg-zinc-800/60 rounded-lg px-4 py-3 text-sm text-zinc-700 dark:text-zinc-200 font-mono", children: buildPurchaseAnnouncementMessage({
161
161
  buyerName: "Ravi K.",
162
162
  firstItemName: "Charizard PSA 9",
163
163
  additionalItemCount: 2,
164
164
  totalAmount: 450000,
165
165
  orderId: "order-3-20260510-a1b2c3",
166
- }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-2", children: "Catalog Preview" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-4", children: "This is how your products appear in the WhatsApp Catalog when a buyer taps \"View Catalog\" in the chat. Only published standard products are included." }), _jsxs(Div, { className: "border border-zinc-200 dark:border-zinc-700 rounded-xl overflow-hidden bg-[#ECE5DD] dark:bg-zinc-800 p-3", children: [_jsxs(Row, { gap: "sm", align: "center", className: "mb-3", children: [_jsx(Div, { className: "w-8 h-8 rounded-full bg-[#25D366] flex items-center justify-center", children: _jsx(Text, { className: "text-white text-xs font-bold", children: "W" }) }), _jsxs(Div, { children: [_jsx(Text, { className: "text-xs font-semibold text-zinc-900 dark:text-zinc-100", children: cfg?.connected ? "Your Store" : "Store Name" }), _jsx(Text, { className: "text-[10px] text-zinc-500 dark:text-zinc-400", children: "WhatsApp Business" })] })] }), _jsx(Div, { className: "grid grid-cols-2 gap-2", children: SAMPLE_CATALOG_ITEMS.map((item) => (_jsxs(Div, { className: "bg-white dark:bg-zinc-900 rounded-lg overflow-hidden shadow-sm", children: [_jsx(Div, { className: "aspect-square bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center", children: _jsx(Text, { className: "text-2xl", children: item.emoji }) }), _jsxs(Div, { className: "p-2", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-900 dark:text-zinc-100 line-clamp-2 leading-tight", children: item.name }), _jsx(Text, { className: "text-xs text-[#25D366] font-semibold mt-0.5", children: item.price })] })] }, item.id))) }), _jsx(Div, { className: "mt-3 text-center", children: _jsx(Text, { className: "text-[10px] text-zinc-500 dark:text-zinc-400", children: cfg?.lastSyncCount
166
+ }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100 mb-2", children: "Catalog Preview" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-4", children: "This is how your products appear in the WhatsApp Catalog when a buyer taps \"View Catalog\" in the chat. Only published standard products are included." }), _jsxs(Div, { className: "border border-zinc-200 dark:border-zinc-700 rounded-xl overflow-hidden bg-[#ECE5DD] dark:bg-zinc-800 p-3", children: [_jsxs(Row, { gap: "sm", align: "center", className: "mb-3", children: [_jsx(Div, { className: "w-8 h-8 rounded-full bg-[#25D366] flex items-center justify-center", children: _jsx(Text, { className: "text-white text-xs font-bold", children: "W" }) }), _jsxs(Div, { children: [_jsx(Text, { className: "text-xs font-semibold text-zinc-900 dark:text-zinc-100", children: cfg?.connected ? "Your Store" : "Store Name" }), _jsx(Text, { className: "text-[10px] text-zinc-500 dark:text-zinc-400", children: "WhatsApp Business" })] })] }), _jsx(Div, { className: "grid grid-cols-2 gap-2", children: SAMPLE_CATALOG_ITEMS.map((item) => (_jsxs(Div, { surface: "card", className: "overflow-hidden", children: [_jsx(Div, { className: "aspect-square bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center", children: _jsx(Text, { className: "text-2xl", children: item.emoji }) }), _jsxs(Div, { className: "p-2", children: [_jsx(Text, { className: "text-xs font-medium text-zinc-900 dark:text-zinc-100 line-clamp-2 leading-tight", children: item.name }), _jsx(Text, { className: "text-xs text-[#25D366] font-semibold mt-0.5", children: item.price })] })] }, item.id))) }), _jsx(Div, { className: "mt-3 text-center", children: _jsx(Text, { className: "text-[10px] text-zinc-500 dark:text-zinc-400", children: cfg?.lastSyncCount
167
167
  ? `${cfg.lastSyncCount} products synced to catalog`
168
- : "Sync your products to populate the catalog" }) })] }), !cfg?.connected && (_jsx(Text, { className: "text-xs text-amber-600 dark:text-amber-400 mt-2", children: "Connect your WhatsApp Business account above to enable the catalog." }))] })] }));
168
+ : "Sync your products to populate the catalog" }) })] }), !cfg?.connected && (_jsx(Text, { className: "text-xs text-warning mt-2", children: "Connect your WhatsApp Business account above to enable the catalog." }))] })] }));
169
169
  }
@@ -3,7 +3,7 @@ import { Button, Div, Stack, Text } from "../../../ui";
3
3
  import { formatCurrency } from "../../../utils/number.formatter";
4
4
  import { THEME_CONSTANTS } from "../../../tokens";
5
5
  export function WishlistCard({ item, onRemove, onProductClick, }) {
6
- return (_jsxs(Div, { className: "flex gap-4 rounded-xl border border-neutral-200 dark:border-slate-700 bg-white dark:bg-slate-900 p-4", children: [_jsx(Div, { role: onProductClick ? "button" : undefined, tabIndex: onProductClick ? 0 : undefined, onClick: onProductClick ? () => onProductClick(item) : undefined, onKeyDown: onProductClick
6
+ return (_jsxs(Div, { surface: "card", padding: "sm", className: "flex gap-4", children: [_jsx(Div, { role: onProductClick ? "button" : undefined, tabIndex: onProductClick ? 0 : undefined, onClick: onProductClick ? () => onProductClick(item) : undefined, onKeyDown: onProductClick
7
7
  ? (e) => e.key === "Enter" && onProductClick(item)
8
8
  : undefined, className: `h-20 w-20 flex-shrink-0 overflow-hidden rounded-lg bg-neutral-100 dark:bg-slate-800 ${onProductClick ? "cursor-pointer" : ""}`, children: item.productImage && (_jsx(Div, { role: "img", "aria-label": item.productTitle ?? "", className: "h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${item.productImage})` } })) }), _jsxs(Div, { className: "flex flex-1 flex-col justify-between", children: [_jsx(Text, { className: `font-medium text-neutral-900 dark:text-zinc-100 ${THEME_CONSTANTS.utilities.textClamp2}`, children: item.productTitle }), item.productPrice !== undefined && (_jsx(Text, { className: "text-sm font-semibold text-neutral-900 dark:text-zinc-100", children: formatCurrency(item.productPrice, item.productCurrency) }))] }), onRemove && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onRemove(item.id), "aria-label": "Remove from wishlist", className: "self-start text-zinc-400 dark:text-zinc-400 transition hover:text-red-500", children: "\u2715" }))] }));
9
9
  }
package/dist/index.d.ts CHANGED
@@ -501,12 +501,9 @@ export { FirebaseFAQsRepository } from "./repositories/index";
501
501
  export { NewsletterRepository } from "./repositories/index";
502
502
  export { OfferRepository } from "./repositories/index";
503
503
  export { OrderRepository } from "./repositories/index";
504
- export { OrdersRepository } from "./repositories/index";
505
504
  export { PasswordResetTokenRepository } from "./repositories/index";
506
505
  export { ProductRepository } from "./repositories/index";
507
- export { ProductsRepository } from "./repositories/index";
508
506
  export { ReviewRepository } from "./repositories/index";
509
- export { ReviewsRepository } from "./repositories/index";
510
507
  export { SessionRepository } from "./repositories/index";
511
508
  export { SmsCounterRepository } from "./repositories/index";
512
509
  export { StoreRepository } from "./repositories/index";
@@ -1162,7 +1159,6 @@ export { DEFAULT_NOTIFICATION_DATA } from "./features/admin/index";
1162
1159
  export { DEFAULT_SITE_SETTINGS_DATA } from "./features/admin/index";
1163
1160
  export { DEFAULT_TRUST_BAR_ITEMS } from "./features/admin/index";
1164
1161
  export { DashboardStatsGrid } from "./features/admin/index";
1165
- export { DemoSeedView } from "./features/admin/index";
1166
1162
  export { AdminTeamView } from "./features/admin/index";
1167
1163
  export { AdminEmployeeEditorView } from "./features/admin/index";
1168
1164
  export { AdminSupportTicketsView } from "./features/admin/index";
@@ -1240,7 +1236,6 @@ export type { ChatRoomCreateInput } from "./features/admin/index";
1240
1236
  export type { ChatRoomDocument } from "./features/admin/index";
1241
1237
  export type { ChatRoomUpdateInput } from "./features/admin/index";
1242
1238
  export type { DashboardStats } from "./features/admin/index";
1243
- export type { DemoSeedViewProps } from "./features/admin/index";
1244
1239
  export type { AdminTeamViewProps } from "./features/admin/index";
1245
1240
  export type { AdminEmployeeEditorViewProps } from "./features/admin/index";
1246
1241
  export type { AdminSupportTicketsViewProps } from "./features/admin/index";
@@ -2137,6 +2132,7 @@ export { LoyaltyRepository } from "./features/loyalty/server";
2137
2132
  export { AvatarUpload } from "./features/media/index";
2138
2133
  export { CameraCapture } from "./features/media/index";
2139
2134
  export { ImageCropModal } from "./features/media/index";
2135
+ export { ImageEditor } from "./features/media/index";
2140
2136
  export { ImageUpload } from "./features/media/index";
2141
2137
  export { MediaAvatar } from "./features/media/index";
2142
2138
  export { MediaImage } from "./features/media/index";
@@ -2157,6 +2153,7 @@ export { useMediaUpload } from "./features/media/index";
2157
2153
  export type { AvatarUploadProps } from "./features/media/index";
2158
2154
  export type { CameraCaptureProps } from "./features/media/index";
2159
2155
  export type { ImageCropData } from "./features/media/index";
2156
+ export type { ImageEditorProps } from "./features/media/index";
2160
2157
  export type { ImageCropModalProps } from "./features/media/index";
2161
2158
  export type { ImageUploadProps } from "./features/media/index";
2162
2159
  export type { LightboxItem } from "./features/media/index";
@@ -2382,6 +2379,7 @@ export { isListingTypeEnabled, isCategoryTypeEnabled, enabledListingTypes, enabl
2382
2379
  export { actionTracker, setActionTrackerSink, resetActionTrackerSink, type ActionEvent, type ActionTrackerSink, } from "./_internal/shared/listing-types/action-tracker";
2383
2380
  export { cartRequiresShipping, cartIsDigitalOnly, cartIsChatOnly, } from "./_internal/shared/listing-types/cart-shipping";
2384
2381
  export { ACTIONS, action, act, canPerformAction, actionsForListingType, actionLabel, type ActionDef, type ActionKind, type ActionResource, type ActionTree, type ActionConfirmation, } from "./_internal/shared/actions/action-registry";
2382
+ export { buildBulkAction } from "./_internal/shared/actions/bulk-helpers";
2385
2383
  export { isAdminUser, isSellerUser, isModeratorUser, isEmployeeUser, isBuyerUser, } from "./features/auth/role-predicates";
2386
2384
  export { sanitizeProductForPublic, sanitizeProductsForPublic } from "./features/products/index";
2387
2385
  export { productAdminColumns } from "./features/products/index";
@@ -3004,7 +3002,7 @@ export { API_ENDPOINTS, API_ROUTES, LOGS_ENDPOINTS, AUTH_ENDPOINTS, ACCOUNT_ENDP
3004
3002
  export { WishlistFullError } from "./features/wishlist/server";
3005
3003
  export { useHistory, useHistoryMergeOnLogin, getGuestHistory, trackGuestHistory, removeGuestHistoryItem, clearGuestHistory, getGuestHistoryCount, type GuestHistoryItem, type GuestHistoryType, type UserHistoryItem, type HistoryProductType, type HistoryItemSnapshot, type TrackArgs as TrackHistoryArgs, } from "./features/history";
3006
3004
  export { historyRepository, UserHistoryRepository, trackHistoryView, getHistoryForUser, removeHistoryItem, clearHistory, mergeGuestHistory, } from "./features/history/server";
3007
- export { useMediaQuery, useBreakpoint, useClickOutside, useKeyPress, useLongPress, useGesture, useSwipe, ThemeProvider, useTheme, useSession, useAuth, useCountdown, useCamera, useBulkSelection, useUrlTable, usePendingFilters, usePendingTable, useUnsavedChanges, UNSAVED_CHANGES_EVENT, useBulkAction, useContainerGrid, useMessage, useVisibleItems, useModalStack, RTDBPayloadStatus, } from "./react/index";
3005
+ export { useMediaQuery, useBreakpoint, useClickOutside, useKeyPress, useLongPress, useGesture, useSwipe, ThemeProvider, useTheme, useSession, useAuth, useCountdown, useCamera, useBulkSelection, useUrlTable, usePendingFilters, usePendingTable, useUnsavedChanges, UNSAVED_CHANGES_EVENT, useBulkAction, useEntityDelete, useContainerGrid, useMessage, useVisibleItems, useModalStack, RTDBPayloadStatus, } from "./react/index";
3008
3006
  export { RoleGate, ProtectedRoute, SocialAuthButtons, AuthStatusPanel, LoginForm, RegisterForm, ForgotPasswordView, ResetPasswordView, VerifyEmailView, OAuthLoadingView, } from "./features/auth/index";
3009
3007
  export type { RoleGateProps, ProtectedRouteProps, AuthGuardUser, AuthRouteConfig, LoginFormProps, LoginFormValues, RegisterFormProps, RegisterFormValues, ForgotPasswordViewProps, ResetPasswordViewProps, VerifyEmailViewProps, } from "./features/auth/index";
3010
3008
  export { CartItemRow, CartDrawer, CartView, CartSummary, ShippingPicker } from "./features/cart/index";
package/dist/index.js CHANGED
@@ -977,24 +977,15 @@ export { OfferRepository } from "./repositories/index";
977
977
  // OrderRepository - Shared export for order repository.
978
978
  export { OrderRepository } from "./repositories/index";
979
979
  // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
980
- // OrdersRepository - Shared export for orders repository.
981
- export { OrdersRepository } from "./repositories/index";
982
- // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
983
980
  // PasswordResetTokenRepository - Shared export for password reset token repository.
984
981
  export { PasswordResetTokenRepository } from "./repositories/index";
985
982
  // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
986
983
  // ProductRepository - Shared export for product repository.
987
984
  export { ProductRepository } from "./repositories/index";
988
985
  // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
989
- // ProductsRepository - Shared export for products repository.
990
- export { ProductsRepository } from "./repositories/index";
991
- // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
992
986
  // ReviewRepository - Shared export for review repository.
993
987
  export { ReviewRepository } from "./repositories/index";
994
988
  // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
995
- // ReviewsRepository - Shared export for reviews repository.
996
- export { ReviewsRepository } from "./repositories/index";
997
- // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
998
989
  // SessionRepository - Shared export for session repository.
999
990
  export { SessionRepository } from "./repositories/index";
1000
991
  // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
@@ -2258,8 +2249,7 @@ export { DEFAULT_TRUST_BAR_ITEMS } from "./features/admin/index";
2258
2249
  // DashboardStatsGrid - Component for dashboard stats grid.
2259
2250
  export { DashboardStatsGrid } from "./features/admin/index";
2260
2251
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
2261
- // DemoSeedView - Component for demo seed view.
2262
- export { DemoSeedView } from "./features/admin/index";
2252
+ // DemoSeedView — removed from main barrel (dev-only, load via dynamic import)
2263
2253
  // AdminTeamView - Employee management list view.
2264
2254
  export { AdminTeamView } from "./features/admin/index";
2265
2255
  // AdminEmployeeEditorView - Invite/edit employee permissions SideDrawer.
@@ -3986,6 +3976,9 @@ export { CameraCapture } from "./features/media/index";
3986
3976
  // [CLIENT-ONLY]-Cannot run in SSR mode â€" uses browser-only APIs (window, navigator, localStorage, matchMedia, DOM events) that do not exist in Node.js.
3987
3977
  // ImageCropModal - Component for image crop modal.
3988
3978
  export { ImageCropModal } from "./features/media/index";
3979
+ // [CLIENT-ONLY]-Cannot run in SSR mode — uses browser-only APIs.
3980
+ // ImageEditor - Advanced crop/rotate/zoom editor (react-advanced-cropper).
3981
+ export { ImageEditor } from "./features/media/index";
3989
3982
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3990
3983
  // ImageUpload - Shared export for image upload.
3991
3984
  export { ImageUpload } from "./features/media/index";
@@ -4432,6 +4425,7 @@ export { actionTracker, setActionTrackerSink, resetActionTrackerSink, } from "./
4432
4425
  export { cartRequiresShipping, cartIsDigitalOnly, cartIsChatOnly, } from "./_internal/shared/listing-types/cart-shipping";
4433
4426
  // SB-UNI-W-1 2026-05-13 â€" CTA action registry shell.
4434
4427
  export { ACTIONS, action, act, canPerformAction, actionsForListingType, actionLabel, } from "./_internal/shared/actions/action-registry";
4428
+ export { buildBulkAction } from "./_internal/shared/actions/bulk-helpers";
4435
4429
  // User-role predicates â€" SB-UNI-E 2026-05-13.
4436
4430
  export { isAdminUser, isSellerUser, isModeratorUser, isEmployeeUser, isBuyerUser, } from "./features/auth/role-predicates";
4437
4431
  // [SERVER-ONLY]-Safe in browser but intended for server routes.
@@ -5437,7 +5431,7 @@ export { WishlistFullError } from "./features/wishlist/server";
5437
5431
  export { useHistory, useHistoryMergeOnLogin, getGuestHistory, trackGuestHistory, removeGuestHistoryItem, clearGuestHistory, getGuestHistoryCount, } from "./features/history";
5438
5432
  export { historyRepository, UserHistoryRepository, trackHistoryView, getHistoryForUser, removeHistoryItem, clearHistory, mergeGuestHistory, } from "./features/history/server";
5439
5433
  // Missing React hooks and providers
5440
- export { useMediaQuery, useBreakpoint, useClickOutside, useKeyPress, useLongPress, useGesture, useSwipe, ThemeProvider, useTheme, useSession, useAuth, useCountdown, useCamera, useBulkSelection, useUrlTable, usePendingFilters, usePendingTable, useUnsavedChanges, UNSAVED_CHANGES_EVENT, useBulkAction, useContainerGrid, useMessage, useVisibleItems, useModalStack, RTDBPayloadStatus, } from "./react/index";
5434
+ export { useMediaQuery, useBreakpoint, useClickOutside, useKeyPress, useLongPress, useGesture, useSwipe, ThemeProvider, useTheme, useSession, useAuth, useCountdown, useCamera, useBulkSelection, useUrlTable, usePendingFilters, usePendingTable, useUnsavedChanges, UNSAVED_CHANGES_EVENT, useBulkAction, useEntityDelete, useContainerGrid, useMessage, useVisibleItems, useModalStack, RTDBPayloadStatus, } from "./react/index";
5441
5435
  // Missing core types (already exported above; skipped to avoid duplicates)
5442
5436
  // Missing auth feature components
5443
5437
  export { RoleGate, ProtectedRoute, SocialAuthButtons, AuthStatusPanel, LoginForm, RegisterForm, ForgotPasswordView, ResetPasswordView, VerifyEmailView, OAuthLoadingView, } from "./features/auth/index";
@@ -32,6 +32,8 @@ export interface SessionUser {
32
32
  scamAwarenessAcknowledgedAt?: Date | null;
33
33
  /** RBAC permission keys granted to this user (from their role's permission set). */
34
34
  permissions?: string[];
35
+ /** Hash of the last dismissed announcement banner. */
36
+ dismissedBannerHash?: string;
35
37
  }
36
38
  export interface SessionContextValue {
37
39
  user: SessionUser | null;