@mohasinac/appkit 2.7.53 → 2.7.55

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 (197) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
  2. package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -3
  3. package/dist/_internal/server/jobs/core/bundleStockSync.js +9 -7
  4. package/dist/_internal/server/jobs/core/onProductStockChange.d.ts +12 -3
  5. package/dist/_internal/server/jobs/core/onProductStockChange.js +12 -13
  6. package/dist/_internal/server/jobs/core/onProductWrite.js +1 -3
  7. package/dist/_internal/server/jobs/handlers/onProductStockChange.js +11 -2
  8. package/dist/_internal/server/jobs/runtime/adapters/firebase.js +5 -14
  9. package/dist/_internal/shared/actions/action-registry.js +827 -4
  10. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  11. package/dist/client.d.ts +2 -0
  12. package/dist/client.js +1 -0
  13. package/dist/constants/api-endpoints.d.ts +3 -0
  14. package/dist/constants/api-endpoints.js +1 -0
  15. package/dist/constants/field-names.d.ts +4 -3
  16. package/dist/constants/field-names.js +8 -8
  17. package/dist/errors/error-codes.d.ts +3 -0
  18. package/dist/errors/error-codes.js +3 -0
  19. package/dist/errors/messages.d.ts +3 -0
  20. package/dist/errors/messages.js +3 -0
  21. package/dist/features/account/components/UserOffersPanel.js +2 -1
  22. package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -3
  23. package/dist/features/admin/components/AdminBidsView.js +5 -3
  24. package/dist/features/admin/components/AdminBlogView.js +3 -2
  25. package/dist/features/admin/components/AdminBrandsView.js +2 -1
  26. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  27. package/dist/features/admin/components/AdminBundlesView.js +3 -3
  28. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -1
  29. package/dist/features/admin/components/AdminCarouselView.js +14 -5
  30. package/dist/features/admin/components/AdminCategoriesView.js +2 -1
  31. package/dist/features/admin/components/AdminContactView.d.ts +4 -1
  32. package/dist/features/admin/components/AdminContactView.js +27 -7
  33. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -1
  34. package/dist/features/admin/components/AdminCouponsView.js +17 -3
  35. package/dist/features/admin/components/AdminFaqsView.d.ts +3 -1
  36. package/dist/features/admin/components/AdminFaqsView.js +18 -4
  37. package/dist/features/admin/components/AdminFeaturesView.js +2 -1
  38. package/dist/features/admin/components/AdminMediaView.js +3 -2
  39. package/dist/features/admin/components/AdminNavigationView.js +3 -2
  40. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -1
  41. package/dist/features/admin/components/AdminNewsletterView.js +13 -4
  42. package/dist/features/admin/components/AdminNotificationsView.js +6 -4
  43. package/dist/features/admin/components/AdminOrdersView.js +4 -3
  44. package/dist/features/admin/components/AdminPayoutsView.js +2 -2
  45. package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -1
  46. package/dist/features/admin/components/AdminProductsView.js +3 -3
  47. package/dist/features/admin/components/AdminReviewsView.js +4 -3
  48. package/dist/features/admin/components/AdminScammersView.js +2 -1
  49. package/dist/features/admin/components/AdminSessionsView.js +5 -3
  50. package/dist/features/admin/components/AdminStoresView.js +2 -2
  51. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +5 -1
  52. package/dist/features/admin/components/AdminSublistingCategoriesView.js +12 -3
  53. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -1
  54. package/dist/features/admin/components/AdminTeamView.d.ts +2 -1
  55. package/dist/features/admin/components/AdminTeamView.js +13 -4
  56. package/dist/features/admin/components/AdminUsersView.js +2 -2
  57. package/dist/features/admin/types/product.types.d.ts +1 -1
  58. package/dist/features/admin/types/product.types.js +2 -3
  59. package/dist/features/auctions/actions/bid-actions.d.ts +9 -0
  60. package/dist/features/auctions/actions/bid-actions.js +61 -0
  61. package/dist/features/auctions/components/AuctionDetailPageView.d.ts +2 -1
  62. package/dist/features/auctions/components/AuctionDetailPageView.js +5 -4
  63. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +3 -1
  64. package/dist/features/auctions/components/PlaceBidFormClient.js +32 -2
  65. package/dist/features/auctions/types/index.d.ts +1 -1
  66. package/dist/features/layout/AppLayoutShell.js +1 -1
  67. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -11
  68. package/dist/features/products/api/[id]/route.js +4 -8
  69. package/dist/features/products/api/route.js +1 -3
  70. package/dist/features/products/components/AuctionsIndexListing.js +3 -11
  71. package/dist/features/products/components/PrizeDrawsIndexListing.js +2 -10
  72. package/dist/features/products/components/ProductFilters.d.ts +33 -9
  73. package/dist/features/products/components/ProductFilters.js +6 -29
  74. package/dist/features/products/components/ProductForm.js +2 -3
  75. package/dist/features/products/constants/action-defs.d.ts +86 -7
  76. package/dist/features/products/constants/action-defs.js +99 -7
  77. package/dist/features/products/constants/sieve.d.ts +162 -0
  78. package/dist/features/products/constants/sieve.js +95 -0
  79. package/dist/features/products/repository/products.repository.d.ts +5 -0
  80. package/dist/features/products/repository/products.repository.js +23 -3
  81. package/dist/features/products/schemas/firestore.d.ts +4 -4
  82. package/dist/features/products/schemas/firestore.js +2 -3
  83. package/dist/features/products/schemas/index.d.ts +6 -6
  84. package/dist/features/products/schemas/index.js +2 -6
  85. package/dist/features/products/types/index.d.ts +1 -1
  86. package/dist/features/seller/actions/offer-actions.js +2 -2
  87. package/dist/features/seller/components/QuickProductForm.d.ts +13 -0
  88. package/dist/features/seller/components/QuickProductForm.js +50 -0
  89. package/dist/features/seller/components/SellerAuctionsView.d.ts +4 -1
  90. package/dist/features/seller/components/SellerAuctionsView.js +37 -3
  91. package/dist/features/seller/components/SellerBidsView.js +2 -1
  92. package/dist/features/seller/components/SellerBundlesView.d.ts +3 -1
  93. package/dist/features/seller/components/SellerBundlesView.js +38 -5
  94. package/dist/features/seller/components/SellerClassifiedView.d.ts +3 -1
  95. package/dist/features/seller/components/SellerClassifiedView.js +37 -4
  96. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +3 -1
  97. package/dist/features/seller/components/SellerDigitalCodesView.js +37 -4
  98. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -1
  99. package/dist/features/seller/components/SellerGroupedListingsView.js +3 -2
  100. package/dist/features/seller/components/SellerLiveView.d.ts +3 -1
  101. package/dist/features/seller/components/SellerLiveView.js +37 -4
  102. package/dist/features/seller/components/SellerOffersPanel.js +2 -1
  103. package/dist/features/seller/components/SellerOffersView.d.ts +4 -1
  104. package/dist/features/seller/components/SellerOffersView.js +8 -3
  105. package/dist/features/seller/components/SellerPayoutsView.d.ts +3 -1
  106. package/dist/features/seller/components/SellerPayoutsView.js +7 -3
  107. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -1
  108. package/dist/features/seller/components/SellerPreOrdersView.js +30 -7
  109. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -1
  110. package/dist/features/seller/components/SellerPrizeDrawsView.js +30 -7
  111. package/dist/features/seller/components/SellerProductShell.js +12 -0
  112. package/dist/features/seller/components/SellerReviewsView.js +2 -1
  113. package/dist/features/seller/components/SellerShippingConfigsView.js +3 -2
  114. package/dist/features/seller/components/SellerStoreCategoriesView.js +6 -5
  115. package/dist/features/seller/components/SellerTemplatesView.js +4 -3
  116. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +30 -16
  117. package/dist/features/wishlist/types/index.d.ts +1 -1
  118. package/dist/index.d.ts +6 -3
  119. package/dist/index.js +6 -4
  120. package/dist/seed/addresses-seed-data.d.ts +2 -18
  121. package/dist/seed/addresses-seed-data.js +137 -203
  122. package/dist/seed/bids-seed-data.d.ts +2 -8
  123. package/dist/seed/bids-seed-data.js +172 -648
  124. package/dist/seed/blog-posts-seed-data.d.ts +0 -5
  125. package/dist/seed/blog-posts-seed-data.js +341 -596
  126. package/dist/seed/carousel-slides-seed-data.d.ts +0 -5
  127. package/dist/seed/carousel-slides-seed-data.js +61 -192
  128. package/dist/seed/carousels-seed-data.js +18 -1
  129. package/dist/seed/cart-seed-data.d.ts +1 -18
  130. package/dist/seed/cart-seed-data.js +116 -293
  131. package/dist/seed/categories-seed-data.d.ts +0 -6
  132. package/dist/seed/categories-seed-data.js +1409 -1537
  133. package/dist/seed/claimed-coupons-seed-data.d.ts +0 -11
  134. package/dist/seed/claimed-coupons-seed-data.js +32 -29
  135. package/dist/seed/conversations-seed-data.d.ts +0 -6
  136. package/dist/seed/conversations-seed-data.js +132 -280
  137. package/dist/seed/coupon-usage-seed-data.d.ts +0 -16
  138. package/dist/seed/coupon-usage-seed-data.js +30 -44
  139. package/dist/seed/coupons-seed-data.d.ts +0 -6
  140. package/dist/seed/coupons-seed-data.js +141 -489
  141. package/dist/seed/events-seed-data.d.ts +0 -6
  142. package/dist/seed/events-seed-data.js +201 -379
  143. package/dist/seed/faq-seed-data.d.ts +0 -14
  144. package/dist/seed/faq-seed-data.js +609 -1184
  145. package/dist/seed/grouped-listings-seed-data.d.ts +119 -8
  146. package/dist/seed/grouped-listings-seed-data.js +148 -233
  147. package/dist/seed/history-seed-data.d.ts +0 -7
  148. package/dist/seed/history-seed-data.js +50 -54
  149. package/dist/seed/homepage-sections-seed-data.d.ts +0 -5
  150. package/dist/seed/homepage-sections-seed-data.js +83 -175
  151. package/dist/seed/index.d.ts +1 -1
  152. package/dist/seed/index.js +1 -1
  153. package/dist/seed/manifest.js +2 -2
  154. package/dist/seed/notifications-seed-data.d.ts +0 -6
  155. package/dist/seed/notifications-seed-data.js +309 -196
  156. package/dist/seed/offers-seed-data.d.ts +0 -8
  157. package/dist/seed/offers-seed-data.js +118 -197
  158. package/dist/seed/orders-seed-data.d.ts +2 -8
  159. package/dist/seed/orders-seed-data.js +248 -1510
  160. package/dist/seed/payouts-seed-data.d.ts +0 -6
  161. package/dist/seed/payouts-seed-data.js +102 -441
  162. package/dist/seed/products-auctions-seed-data.d.ts +1 -14
  163. package/dist/seed/products-auctions-seed-data.js +612 -1084
  164. package/dist/seed/products-preorders-seed-data.d.ts +119 -14
  165. package/dist/seed/products-preorders-seed-data.js +154 -455
  166. package/dist/seed/products-standard-seed-data.d.ts +1 -15
  167. package/dist/seed/products-standard-seed-data.js +1355 -4128
  168. package/dist/seed/reviews-seed-data.d.ts +2 -8
  169. package/dist/seed/reviews-seed-data.js +99 -1182
  170. package/dist/seed/scammers-seed-data.d.ts +0 -15
  171. package/dist/seed/scammers-seed-data.js +36 -37
  172. package/dist/seed/sessions-seed-data.d.ts +0 -13
  173. package/dist/seed/sessions-seed-data.js +58 -335
  174. package/dist/seed/site-settings-seed-data.d.ts +0 -4
  175. package/dist/seed/site-settings-seed-data.js +61 -52
  176. package/dist/seed/store-addresses-seed-data.js +27 -151
  177. package/dist/seed/store-extensions-seed-data.d.ts +0 -7
  178. package/dist/seed/store-extensions-seed-data.js +147 -261
  179. package/dist/seed/stores-seed-data.d.ts +0 -5
  180. package/dist/seed/stores-seed-data.js +222 -184
  181. package/dist/seed/sub-listings-seed-data.d.ts +119 -0
  182. package/dist/seed/sub-listings-seed-data.js +447 -0
  183. package/dist/seed/support-tickets-seed-data.d.ts +0 -7
  184. package/dist/seed/support-tickets-seed-data.js +82 -75
  185. package/dist/seed/users-seed-data.d.ts +0 -5
  186. package/dist/seed/users-seed-data.js +279 -634
  187. package/dist/seed/wishlists-seed-data.d.ts +0 -9
  188. package/dist/seed/wishlists-seed-data.js +36 -52
  189. package/dist/seo/json-ld.js +6 -4
  190. package/dist/styles.css +8052 -3
  191. package/dist/tailwind-utilities.css +1 -1
  192. package/dist/utils/index.d.ts +1 -0
  193. package/dist/utils/index.js +1 -0
  194. package/dist/utils/search-tokens.d.ts +2 -0
  195. package/dist/utils/search-tokens.js +21 -0
  196. package/package.json +2 -2
  197. package/scripts/seed-cli.mjs +2 -2
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useCallback, useEffect, useMemo, useState } from "react";
4
4
  import { Alert, Badge, BulkActionBar, Button, Checkbox, Div, Modal, Row, Select, SideDrawer, Stack, Text, Textarea, } from "../../../ui";
5
5
  import { StackedViewShell } from "../../../ui";
6
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
6
7
  const STAR = "★";
7
8
  const EMPTY_STAR = "☆";
8
9
  function Stars({ rating }) {
@@ -158,6 +159,6 @@ export function SellerReviewsView({ reviewsApiBase = "/api/store/reviews", reply
158
159
  label: "Reply to selected",
159
160
  onClick: () => setBulkReplyOpen(true),
160
161
  },
161
- ] })), loading ? (_jsx(Div, { className: "py-8 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Loading reviews\u2026" }) })) : reviews.length === 0 ? (_jsx(Div, { className: "py-12 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "No reviews found." }) })) : (_jsx(Stack, { gap: "md", children: reviews.map((review) => (_jsx(Div, { className: "p-4 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: _jsxs(Div, { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs(Row, { className: "gap-3 items-start flex-1 min-w-0", children: [_jsx(Checkbox, { checked: selectedIds.has(review.id), onChange: () => toggleSelected(review.id), "aria-label": "Select review" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "font-medium truncate", children: review.productTitle }), _jsxs(Div, { className: "flex items-center gap-2 mt-1 flex-wrap", children: [_jsx(Stars, { rating: review.rating }), _jsxs(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: ["by ", review.userName] }), review.verified && _jsx(Badge, { variant: "success", children: "Verified" }), statusBadge(review.status), _jsx(Badge, { variant: review.sellerReply ? "success" : "warning", children: review.sellerReply ? "Store replied" : "Awaiting store reply" })] }), review.title && _jsx(Text, { className: "mt-2 font-medium", children: review.title }), _jsx(Text, { className: "mt-1 text-sm text-[var(--appkit-color-text-secondary)] line-clamp-3", children: review.comment }), review.sellerReply && (_jsxs(Div, { className: "mt-2 pl-3 border-l-2 border-[var(--appkit-color-primary)]", children: [_jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)]", children: "Store reply:" }), _jsx(Text, { className: "text-sm", children: review.sellerReply })] }))] })] }), _jsxs(Row, { className: "gap-2 flex-shrink-0", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => openReply(review), children: review.sellerReply ? "Edit Reply" : "Reply" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setContestTarget(review), children: "Contest" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setFeedbackTarget(review), children: "Feedback" })] })] }) }, review.id))) })), meta && meta.totalPages > 1 && (_jsxs(Div, { className: "flex items-center justify-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: page <= 1 || loading, children: "Previous" }), _jsxs(Text, { className: "text-sm", children: ["Page ", meta.page, " of ", meta.totalPages] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => p + 1), disabled: !meta.hasMore || loading, children: "Next" })] }))] }, "reviews"),
162
+ ] })), loading ? (_jsx(Div, { className: "py-8 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "Loading reviews\u2026" }) })) : reviews.length === 0 ? (_jsx(Div, { className: "py-12 text-center", children: _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", children: "No reviews found." }) })) : (_jsx(Stack, { gap: "md", children: reviews.map((review) => (_jsx(Div, { className: "p-4 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", children: _jsxs(Div, { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs(Row, { className: "gap-3 items-start flex-1 min-w-0", children: [_jsx(Checkbox, { checked: selectedIds.has(review.id), onChange: () => toggleSelected(review.id), "aria-label": "Select review" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "font-medium truncate", children: review.productTitle }), _jsxs(Div, { className: "flex items-center gap-2 mt-1 flex-wrap", children: [_jsx(Stars, { rating: review.rating }), _jsxs(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: ["by ", review.userName] }), review.verified && _jsx(Badge, { variant: "success", children: "Verified" }), statusBadge(review.status), _jsx(Badge, { variant: review.sellerReply ? "success" : "warning", children: review.sellerReply ? "Store replied" : "Awaiting store reply" })] }), review.title && _jsx(Text, { className: "mt-2 font-medium", children: review.title }), _jsx(Text, { className: "mt-1 text-sm text-[var(--appkit-color-text-secondary)] line-clamp-3", children: review.comment }), review.sellerReply && (_jsxs(Div, { className: "mt-2 pl-3 border-l-2 border-[var(--appkit-color-primary)]", children: [_jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)]", children: "Store reply:" }), _jsx(Text, { className: "text-sm", children: review.sellerReply })] }))] })] }), _jsxs(Row, { className: "gap-2 flex-shrink-0", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => openReply(review), children: review.sellerReply ? "Edit Reply" : ACTIONS.STORE["reply-review"].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setContestTarget(review), children: ACTIONS.STORE["contest-review"].label }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setFeedbackTarget(review), children: ACTIONS.STORE["buyer-feedback"].label })] })] }) }, review.id))) })), meta && meta.totalPages > 1 && (_jsxs(Div, { className: "flex items-center justify-center gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: page <= 1 || loading, children: "Previous" }), _jsxs(Text, { className: "text-sm", children: ["Page ", meta.page, " of ", meta.totalPages] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => setPage((p) => p + 1), disabled: !meta.hasMore || loading, children: "Next" })] }))] }, "reviews"),
162
163
  ] }), _jsx(SideDrawer, { isOpen: !!replyTarget, onClose: () => setReplyTarget(null), title: replyTarget?.sellerReply ? "Edit Reply" : "Reply to Review", mode: "create", children: _jsxs(Stack, { gap: "md", className: "p-4", children: [replyTarget && (_jsxs(Div, { className: "p-3 rounded bg-[var(--appkit-color-surface-muted)]", children: [_jsx(Stars, { rating: replyTarget.rating }), _jsx(Text, { className: "text-sm mt-1", children: replyTarget.comment })] })), replyError && _jsx(Alert, { variant: "error", children: replyError }), _jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium mb-1.5", children: "Store reply" }), _jsx("textarea", { className: "w-full rounded-md border border-[var(--appkit-color-border)] bg-[var(--appkit-color-input-bg,var(--appkit-color-surface))] p-2.5 text-sm resize-none focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)] dark:bg-[var(--appkit-color-surface-dark,#1e2330)] dark:border-[var(--appkit-color-border-dark)]", rows: 5, value: replyText, onChange: (e) => setReplyText(e.target.value), maxLength: 1000, placeholder: "Write your response to this review\u2026" }), _jsxs(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] text-right mt-1", children: [replyText.length, "/1000"] })] }), _jsxs(Div, { className: "flex gap-2 justify-end", children: [_jsx(Button, { variant: "outline", onClick: () => setReplyTarget(null), disabled: replySaving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: handleReplySave, disabled: replySaving || !replyText.trim(), isLoading: replySaving, children: replyTarget?.sellerReply ? "Update Reply" : "Post Reply" })] })] }) }), _jsx(Modal, { isOpen: bulkReplyOpen, onClose: () => setBulkReplyOpen(false), title: `Bulk reply to ${selectedIds.size} review${selectedIds.size === 1 ? "" : "s"}`, actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setBulkReplyOpen(false), disabled: bulkSaving, children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitBulkReply(), disabled: !bulkReplyText.trim() || bulkSaving, isLoading: bulkSaving, children: "Send reply" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "The same reply will be posted on all selected reviews." }), _jsx(Textarea, { value: bulkReplyText, onChange: (e) => setBulkReplyText(e.target.value), rows: 5, placeholder: "Thanks for your review\u2026", label: "Reply" })] }) }), _jsx(Modal, { isOpen: !!contestTarget, onClose: () => setContestTarget(null), title: "Contest this review", actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setContestTarget(null), children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitContest(), disabled: !contestReason.trim(), children: "Submit" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Flag this review for admin investigation. Provide a clear reason \u2014 fake, abusive, off-topic, etc." }), _jsx(Textarea, { value: contestReason, onChange: (e) => setContestReason(e.target.value), rows: 4, label: "Reason" })] }) }), _jsx(Modal, { isOpen: !!feedbackTarget, onClose: () => setFeedbackTarget(null), title: "Send feedback to buyer", actions: _jsxs(Row, { className: "gap-2", children: [_jsx(Button, { variant: "ghost", onClick: () => setFeedbackTarget(null), children: "Cancel" }), _jsx(Button, { variant: "primary", onClick: () => void submitFeedback(), disabled: !feedbackText.trim(), children: "Send" })] }), children: _jsxs(Stack, { gap: "md", className: "p-1", children: [_jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "Private message sent to the buyer's notification inbox. Does not appear on the public review." }), _jsx(Textarea, { value: feedbackText, onChange: (e) => setFeedbackText(e.target.value), rows: 4, label: "Feedback" })] }) })] }));
163
164
  }
@@ -5,6 +5,7 @@ import { Plus } from "lucide-react";
5
5
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { Button, ConfirmDeleteModal, DataTable, Div, ListingToolbar, RowActionMenu, Text, } from "../../../ui";
7
7
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
8
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
8
9
  import { ROUTES } from "../../..";
9
10
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
10
11
  import { TABLE_KEYS } from "../../../constants/table-keys";
@@ -127,7 +128,7 @@ export function SellerShippingConfigsView({ onCreateClick, onEditClick, onDelete
127
128
  }, [onEditClick]);
128
129
  return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search shipping configs...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: handleCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Config" })] }) }), _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: 3 }).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))) })) : rows.length === 0 ? (_jsxs(Div, { className: "py-16 text-center", children: [_jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No shipping configs yet \u2014 define your first shipping rule" }), _jsx("div", { className: "mt-4", children: _jsx(Button, { size: "sm", onClick: handleCreate, children: "Add shipping config" }) })] })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, actions: (row) => (_jsx(RowActionMenu, { actions: [
129
130
  {
130
- label: "Edit",
131
+ label: ACTIONS.STORE["edit-listing"].label,
131
132
  onClick: () => handleEdit(row.id),
132
133
  },
133
134
  ...(!row.isDefault
@@ -140,7 +141,7 @@ export function SellerShippingConfigsView({ onCreateClick, onEditClick, onDelete
140
141
  ]
141
142
  : []),
142
143
  {
143
- label: "Delete",
144
+ label: ACTIONS.STORE["delete-listing"].label,
144
145
  destructive: true,
145
146
  onClick: () => setDeleteTargetId(row.id),
146
147
  disabled: deletingId === row.id,
@@ -6,6 +6,7 @@ import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
7
7
  import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, ListingToolbar, Pagination, RowActionMenu, Text, } from "../../../ui";
8
8
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
9
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
9
10
  import { ROUTES } from "../../../next";
10
11
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
11
12
  import { TABLE_KEYS } from "../../../constants/table-keys";
@@ -83,18 +84,18 @@ export function SellerStoreCategoriesView({ onCreateClick, onEditClick, onDelete
83
84
  const bulkActions = [
84
85
  ...(onBulkDelete ? [{
85
86
  id: "bulk-delete",
86
- label: "Delete selected",
87
+ label: ACTIONS.STORE["delete-listing"].label,
87
88
  variant: "danger",
88
89
  onClick: async () => { await onBulkDelete(selection.selectedIds); selection.clearSelection(); refetch?.(); },
89
90
  }] : []),
90
91
  ...(onBulkActivate ? [{
91
92
  id: "bulk-activate",
92
- label: "Activate",
93
+ label: ACTIONS.ADMIN["activate-bundle"].label,
93
94
  onClick: async () => { await onBulkActivate(selection.selectedIds); selection.clearSelection(); refetch?.(); },
94
95
  }] : []),
95
96
  ...(onBulkDeactivate ? [{
96
97
  id: "bulk-deactivate",
97
- label: "Deactivate",
98
+ label: ACTIONS.ADMIN["deactivate-bundle"].label,
98
99
  onClick: async () => { await onBulkDeactivate(selection.selectedIds); selection.clearSelection(); refetch?.(); },
99
100
  }] : []),
100
101
  ];
@@ -107,13 +108,13 @@ export function SellerStoreCategoriesView({ onCreateClick, onEditClick, onDelete
107
108
  };
108
109
  return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: 0, searchValue: searchInput, searchPlaceholder: "Search categories by label...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_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: handleNavigateNew, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Category" })] }) }), 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) }) })), 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))) })) : rows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No categories yet \u2014 add your first storefront category" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: rows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
109
110
  {
110
- label: "Edit",
111
+ label: ACTIONS.STORE["edit-listing"].label,
111
112
  onClick: () => onEditClick
112
113
  ? onEditClick(row.id)
113
114
  : (window.location.href = String(ROUTES.STORE.STORE_CATEGORIES_EDIT(row.id))),
114
115
  },
115
116
  ...(onDelete ? [{
116
- label: "Delete",
117
+ label: ACTIONS.STORE["delete-listing"].label,
117
118
  destructive: true,
118
119
  onClick: () => setDeleteTargetId(row.id),
119
120
  disabled: deletingId === row.id,
@@ -6,6 +6,7 @@ import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
7
7
  import { BulkActionBar, Button, ConfirmDeleteModal, DataTable, Div, FilterDrawer, Input, ListingToolbar, Pagination, RowActionMenu, Select, SideDrawer, Stack, Text, } from "../../../ui";
8
8
  import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
9
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
9
10
  import { toRecordArray, toStringValue, useSellerListingData, } from "../hooks/useSellerListingData";
10
11
  import { TABLE_KEYS } from "../../../constants/table-keys";
11
12
  const PAGE_SIZE = 25;
@@ -226,7 +227,7 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
226
227
  const bulkActions = [
227
228
  {
228
229
  id: "bulk-delete",
229
- label: "Delete selected",
230
+ label: ACTIONS.STORE["delete-template"].label,
230
231
  variant: "danger",
231
232
  onClick: async () => {
232
233
  if (onBulkDelete) {
@@ -247,7 +248,7 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
247
248
  ? "No templates match your search or filters"
248
249
  : "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: [
249
250
  {
250
- label: "Edit",
251
+ label: ACTIONS.STORE["edit-template"].label,
251
252
  onClick: () => openEdit(row),
252
253
  },
253
254
  {
@@ -256,7 +257,7 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
256
257
  onClick: () => handleDuplicate(row),
257
258
  },
258
259
  {
259
- label: "Delete",
260
+ label: ACTIONS.STORE["delete-template"].label,
260
261
  destructive: true,
261
262
  onClick: () => setDeleteTargetId(row.id),
262
263
  disabled: deletingId === row.id,
@@ -1,18 +1,19 @@
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 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, Button, Div, Form, FormActions, Heading, Input, Section, Text, Toggle, useToast } from "../../../ui";
6
+ import { Alert, Badge, Button, Div, Form, FormActions, Heading, Input, Row, Section, Stack, Text, Toggle, useToast } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
8
  import { WHATSAPP_SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
9
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
9
10
  import { buildPurchaseAnnouncementMessage } from "../helpers/whatsapp";
10
11
  // ---------------------------------------------------------------------------
11
12
  // Sub-components
12
13
  // ---------------------------------------------------------------------------
13
14
  function MaskedTokenInput({ label, value, onChange, placeholder, helperText, }) {
14
15
  const [revealed, setRevealed] = React.useState(false);
15
- return (_jsxs("div", { className: "relative", children: [_jsx(Input, { label: label, value: value, onChange: (e) => onChange(e.target.value), type: revealed ? "text" : "password", placeholder: placeholder, helperText: helperText }), _jsx("button", { type: "button", onClick: () => setRevealed((r) => !r), className: "absolute right-3 top-8 text-xs text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200", children: revealed ? "Hide" : "Reveal" })] }));
16
+ return (_jsxs(Div, { className: "relative", children: [_jsx(Input, { label: label, value: value, onChange: (e) => onChange(e.target.value), type: revealed ? "text" : "password", placeholder: placeholder, helperText: helperText }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setRevealed((r) => !r), className: "absolute right-3 top-8 text-xs", children: revealed ? "Hide" : "Reveal" })] }));
16
17
  }
17
18
  const STEPS = [
18
19
  {
@@ -46,10 +47,10 @@ const STEPS = [
46
47
  checkKey: "connected",
47
48
  },
48
49
  ];
49
- const STATUS_COLOR = {
50
- success: "bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300",
51
- partial: "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300",
52
- failed: "bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300",
50
+ const STATUS_VARIANT = {
51
+ success: "success",
52
+ partial: "warning",
53
+ failed: "danger",
53
54
  };
54
55
  // ---------------------------------------------------------------------------
55
56
  // Sample catalog items for preview
@@ -115,7 +116,7 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
115
116
  showToast(msg, "error");
116
117
  },
117
118
  });
118
- // Catalog sync mutation
119
+ // Catalog sync mutation (push: site → WhatsApp)
119
120
  const syncMutation = useMutation({
120
121
  mutationFn: async () => apiClient.post(WHATSAPP_SELLER_ENDPOINTS.CATALOG_SYNC, {}),
121
122
  onSuccess: (res) => {
@@ -128,28 +129,41 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
128
129
  showToast(msg, "error");
129
130
  },
130
131
  });
132
+ // Catalog import mutation (pull: WhatsApp → site)
133
+ const importMutation = useMutation({
134
+ mutationFn: async () => apiClient.post(WHATSAPP_SELLER_ENDPOINTS.CATALOG_IMPORT, {}),
135
+ onSuccess: (res) => {
136
+ const r = res ?? {};
137
+ showToast(`Imported ${r.imported ?? 0} product${(r.imported ?? 0) !== 1 ? "s" : ""} from WhatsApp (${r.skipped ?? 0} already synced)`, "success");
138
+ void queryClient.invalidateQueries({ queryKey: ["store", "whatsapp-settings"] });
139
+ },
140
+ onError: (err) => {
141
+ const msg = err instanceof Error ? err.message : "Import failed";
142
+ showToast(msg, "error");
143
+ },
144
+ });
131
145
  if (!hasCapability) {
132
- return (_jsx("div", { className: "max-w-xl mx-auto py-8 px-4", children: _jsxs(Alert, { variant: "warning", children: [_jsx(Text, { className: "font-medium", children: "WhatsApp catalog sync is not enabled for your store." }), _jsx(Text, { className: "text-sm mt-1", children: "Contact LetItRip support to request access to the WhatsApp Business integration." })] }) }));
146
+ return (_jsx(Div, { className: "max-w-xl mx-auto py-8 px-4", children: _jsxs(Alert, { variant: "warning", children: [_jsx(Text, { className: "font-medium", children: "WhatsApp catalog sync is not enabled for your store." }), _jsx(Text, { className: "text-sm mt-1", children: "Contact LetItRip support to request access to the WhatsApp Business integration." })] }) }));
133
147
  }
134
- return (_jsxs("div", { className: "max-w-2xl mx-auto space-y-8 py-6 px-4", children: [_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100 mb-4", children: "How to connect your WhatsApp Business account" }), _jsx("ol", { className: "space-y-3", children: STEPS.map((step) => {
148
+ return (_jsxs(Stack, { gap: "xl", className: "max-w-2xl mx-auto py-6 px-4", children: [_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "text-base font-semibold text-zinc-900 dark:text-zinc-100 mb-4", children: "How to connect your WhatsApp Business account" }), _jsx(Stack, { gap: "sm", children: STEPS.map((step) => {
135
149
  const done = step.checkKey === undefined
136
150
  ? false
137
151
  : step.checkKey === "connected"
138
152
  ? cfg?.connected === true
139
153
  : Boolean(cfg?.[step.checkKey]);
140
- return (_jsxs("li", { className: "flex gap-3", children: [_jsx("span", { className: `flex-shrink-0 w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center mt-0.5 ${done
141
- ? "bg-green-500 text-white"
142
- : "bg-zinc-200 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-300"}`, children: done ? "✓" : step.n }), _jsxs(_Fragment, { children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: step.title }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mt-0.5", children: step.body })] })] }, step.n));
143
- }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsxs("div", { className: "flex items-center justify-between 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("span", { className: "text-xs font-medium px-2 py-0.5 rounded-full bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300", children: "Connected" })) : (_jsx("span", { className: "text-xs font-medium px-2 py-0.5 rounded-full bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400", children: "Not configured" }))] }), _jsxs(Form, { onSubmit: (e) => {
154
+ return (_jsxs(Row, { gap: "sm", align: "start", children: [_jsx(Div, { className: `flex-shrink-0 w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center mt-0.5 ${done
155
+ ? "bg-[var(--appkit-color-success)] text-white"
156
+ : "bg-zinc-200 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-300"}`, children: done ? "✓" : step.n }), _jsxs(Div, { children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: step.title }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mt-0.5", children: step.body })] })] }, step.n));
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) => {
144
158
  e.preventDefault();
145
159
  saveMutation.mutate();
146
- }, 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…" : "Save & Connect" }) })] })] }), _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("div", { className: "flex items-center justify-between mb-4", children: [_jsxs(_Fragment, { 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("div", { className: "flex items-center gap-2 text-xs text-zinc-500 dark:text-zinc-400 mb-3", children: [_jsxs("span", { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs("span", { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx("span", { className: `px-1.5 py-0.5 rounded ${STATUS_COLOR[cfg.lastSyncStatus] ?? ""}`, children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500 mb-3", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : "Sync Now" })] }), _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-500 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-500 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({
147
161
  buyerName: "Ravi K.",
148
162
  firstItemName: "Charizard PSA 9",
149
163
  additionalItemCount: 2,
150
164
  totalAmount: 450000,
151
165
  orderId: "order-3-20260510-a1b2c3",
152
- }) })] }), _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("div", { className: "flex items-center gap-2 mb-3", children: [_jsx("div", { className: "w-8 h-8 rounded-full bg-[#25D366] flex items-center justify-center", children: _jsx("span", { 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("span", { 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, { 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
153
167
  ? `${cfg.lastSyncCount} products synced to catalog`
154
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." }))] })] }));
155
169
  }
@@ -21,7 +21,7 @@ export interface WishlistProductData {
21
21
  price?: number;
22
22
  currency?: string;
23
23
  images?: string[];
24
- status?: "draft" | "published" | "archived" | "sold" | "out_of_stock" | "discontinued";
24
+ status?: "draft" | "published" | "in_review" | "archived";
25
25
  isFeatured?: boolean;
26
26
  /** Canonical listing-kind discriminator (SB1-G Phase 4). */
27
27
  listingType?: "standard" | "auction" | "pre-order" | "prize-draw" | "classified" | "digital-code" | "live";
package/dist/index.d.ts CHANGED
@@ -623,7 +623,7 @@ export { ordersSeedData } from "./seed/index";
623
623
  export { payoutsSeedData } from "./seed/index";
624
624
  export { productsStandardSeedData } from "./seed/index";
625
625
  export { productsAuctionsSeedData } from "./seed/index";
626
- export { productsPreOrdersSeedData } from "./seed/index";
626
+ export { productsPreordersSeedData } from "./seed/index";
627
627
  export { productsPrizeDrawsSeedData } from "./seed/index";
628
628
  export { registerSeedLocale } from "./seed/index";
629
629
  export { reviewsSeedData } from "./seed/index";
@@ -1360,8 +1360,8 @@ export { GET } from "./features/auctions/server";
1360
1360
  export { bidsGET } from "./features/auctions/server";
1361
1361
  export { getBidById } from "./features/auctions/server";
1362
1362
  export { listBidsByProduct } from "./features/auctions/server";
1363
- export { placeBid } from "./features/auctions/server";
1364
- export type { PlaceBidInput } from "./features/auctions/server";
1363
+ export { placeBid, buyNowAuction } from "./features/auctions/server";
1364
+ export type { PlaceBidInput, BuyNowAuctionInput, BuyNowAuctionResult } from "./features/auctions/server";
1365
1365
  export type { PlaceBidResult } from "./features/auctions/server";
1366
1366
  export { CONSENT_OTP_COOLDOWN_MS } from "./features/auth/server";
1367
1367
  export { CONSENT_OTP_EXPIRY_MINUTES } from "./features/auth/server";
@@ -3048,6 +3048,8 @@ export type { ListingParams } from "./utils/listing-params";
3048
3048
  export { PRODUCT_FEATURE_CATEGORY_OPTIONS, PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS, PRODUCT_FEATURE_SCOPE_OPTIONS, PRODUCT_FEATURE_ICON_COLOR_OPTIONS, PRODUCT_FEATURE_SCOPE_TABS, PRODUCT_FEATURE_DEFAULT_DISPLAY_ORDER, PRODUCT_FEATURE_CARD_MAX_VISIBLE, PRODUCT_FEATURE_QUERY_STALE_MS, } from "./features/products/constants/product-features.constants";
3049
3049
  export { CATEGORY_PAGE_TABS, STORE_PAGE_TABS, SELLER_LISTING_TABS, SEARCH_RESULT_TABS, } from "./features/products/constants/listing-tabs";
3050
3050
  export type { ListingTab, CategoryTabId, StoreTabId, SellerListingTabId, SearchTabId, } from "./features/products/constants/listing-tabs";
3051
+ export { STANDARD_SORT_OPTIONS, STANDARD_PUBLIC_SORT_OPTIONS, AUCTION_SORT_OPTIONS, AUCTION_PUBLIC_SORT_OPTIONS, PREORDER_SORT_OPTIONS, BUNDLE_SORT_OPTIONS, PRIZE_DRAW_SORT_OPTIONS, SORT_OPTIONS_BY_LISTING_TYPE, } from "./features/products/constants/sieve";
3052
+ export type { SortOption } from "./features/products/constants/sieve";
3051
3053
  export { ALL_TAB, EMPTY_TAB, ADMIN_PRODUCT_STATUS_TABS, ADMIN_PRODUCT_LISTING_TYPE_TABS, ADMIN_BLOG_STATUS_TABS, ADMIN_USER_STATUS_TABS, ADMIN_USER_ROLE_TABS, ADMIN_STORE_STATUS_TABS, ADMIN_PAYOUT_STATUS_TABS, ADMIN_ORDER_STATUS_TABS, ADMIN_REVIEW_STATUS_TABS, ADMIN_REVIEW_RATING_TABS, ADMIN_BID_STATUS_TABS, ADMIN_CONTACT_STATUS_TABS, ADMIN_NEWSLETTER_STATUS_TABS, ADMIN_EVENT_ENTRY_STATUS_TABS, ADMIN_EVENT_STATUS_TABS, ADMIN_CART_OWNERSHIP_TABS, ADMIN_COUPON_TYPE_TABS, SELLER_PRODUCT_STATUS_TABS, SELLER_AUCTION_STATUS_TABS, SELLER_ORDER_STATUS_TABS, SELLER_OFFER_STATUS_TABS, SELLER_BID_STATUS_TABS, } from "./features/admin/constants/filter-tabs";
3052
3054
  export type { AdminFilterTab } from "./features/admin/constants/filter-tabs";
3053
3055
  export { GROUPED_LISTINGS_COLLECTION } from "./features/grouped/schemas/firestore";
@@ -3119,6 +3121,7 @@ export { TABLE_KEYS, VIEW_MODE } from "./constants/table-keys";
3119
3121
  export type { TableKey, ViewMode } from "./constants/table-keys";
3120
3122
  export { SIEVE_OP, SIEVE_PIPE_OPS, sieveFilter, sieveMultiEq, expandSieveParam, sieveAnd, } from "./utils/sieve-builder";
3121
3123
  export type { SieveOp } from "./utils/sieve-builder";
3124
+ export { buildSearchTokens, tokenizeQuery } from "./utils/search-tokens";
3122
3125
  export { ActionPermissionsManager } from "./features/site-settings/components/ActionPermissionsManager";
3123
3126
  export type { ActionPermissionsManagerProps } from "./features/site-settings/components/ActionPermissionsManager";
3124
3127
  export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
package/dist/index.js CHANGED
@@ -1317,8 +1317,8 @@ export { productsStandardSeedData } from "./seed/index";
1317
1317
  // productsAuctionsSeedData - Seed data for auction product listings.
1318
1318
  export { productsAuctionsSeedData } from "./seed/index";
1319
1319
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1320
- // productsPreOrdersSeedData - Seed data for pre-order product listings.
1321
- export { productsPreOrdersSeedData } from "./seed/index";
1320
+ // productsPreordersSeedData - Seed data for pre-order product listings.
1321
+ export { productsPreordersSeedData } from "./seed/index";
1322
1322
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1323
1323
  // productsPrizeDrawsSeedData - Seed data for prize-draw product listings (SB5-E).
1324
1324
  export { productsPrizeDrawsSeedData } from "./seed/index";
@@ -2546,8 +2546,8 @@ export { getBidById } from "./features/auctions/server";
2546
2546
  // listBidsByProduct - Helper for list bids by product.
2547
2547
  export { listBidsByProduct } from "./features/auctions/server";
2548
2548
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
2549
- // placeBid - Shared export for place bid.
2550
- export { placeBid } from "./features/auctions/server";
2549
+ // placeBid / buyNowAuction - Shared export for bid + buy-now actions.
2550
+ export { placeBid, buyNowAuction } from "./features/auctions/server";
2551
2551
  // ./features/auth/server
2552
2552
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
2553
2553
  // CONSENT_OTP_COOLDOWN_MS - Constant used across modules.
@@ -5488,6 +5488,7 @@ export { LISTING_PARAM_NAMES, parseListingParams, parseListingSearchParams, seri
5488
5488
  export { PRODUCT_FEATURE_CATEGORY_OPTIONS, PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS, PRODUCT_FEATURE_SCOPE_OPTIONS, PRODUCT_FEATURE_ICON_COLOR_OPTIONS, PRODUCT_FEATURE_SCOPE_TABS, PRODUCT_FEATURE_DEFAULT_DISPLAY_ORDER, PRODUCT_FEATURE_CARD_MAX_VISIBLE, PRODUCT_FEATURE_QUERY_STALE_MS, } from "./features/products/constants/product-features.constants";
5489
5489
  // SB10-A listing tab constants
5490
5490
  export { CATEGORY_PAGE_TABS, STORE_PAGE_TABS, SELLER_LISTING_TABS, SEARCH_RESULT_TABS, } from "./features/products/constants/listing-tabs";
5491
+ export { STANDARD_SORT_OPTIONS, STANDARD_PUBLIC_SORT_OPTIONS, AUCTION_SORT_OPTIONS, AUCTION_PUBLIC_SORT_OPTIONS, PREORDER_SORT_OPTIONS, BUNDLE_SORT_OPTIONS, PRIZE_DRAW_SORT_OPTIONS, SORT_OPTIONS_BY_LISTING_TYPE, } from "./features/products/constants/sieve";
5491
5492
  // SB10-C admin + seller filter-chip tab sets (S8 2026-05-13)
5492
5493
  export { ALL_TAB, EMPTY_TAB, ADMIN_PRODUCT_STATUS_TABS, ADMIN_PRODUCT_LISTING_TYPE_TABS, ADMIN_BLOG_STATUS_TABS, ADMIN_USER_STATUS_TABS, ADMIN_USER_ROLE_TABS, ADMIN_STORE_STATUS_TABS, ADMIN_PAYOUT_STATUS_TABS, ADMIN_ORDER_STATUS_TABS, ADMIN_REVIEW_STATUS_TABS, ADMIN_REVIEW_RATING_TABS, ADMIN_BID_STATUS_TABS, ADMIN_CONTACT_STATUS_TABS, ADMIN_NEWSLETTER_STATUS_TABS, ADMIN_EVENT_ENTRY_STATUS_TABS, ADMIN_EVENT_STATUS_TABS, ADMIN_CART_OWNERSHIP_TABS, ADMIN_COUPON_TYPE_TABS, SELLER_PRODUCT_STATUS_TABS, SELLER_AUCTION_STATUS_TABS, SELLER_ORDER_STATUS_TABS, SELLER_OFFER_STATUS_TABS, SELLER_BID_STATUS_TABS, } from "./features/admin/constants/filter-tabs";
5493
5494
  // Grouped listings feature schemas
@@ -5561,6 +5562,7 @@ export { SORT_DIR, sortBy } from "./constants/sort";
5561
5562
  export { TABLE_KEYS, VIEW_MODE } from "./constants/table-keys";
5562
5563
  // ── Sieve query builder ───────────────────────────────────────────────────────
5563
5564
  export { SIEVE_OP, SIEVE_PIPE_OPS, sieveFilter, sieveMultiEq, expandSieveParam, sieveAnd, } from "./utils/sieve-builder";
5565
+ export { buildSearchTokens, tokenizeQuery } from "./utils/search-tokens";
5564
5566
  // [CLIENT-ONLY] — Admin panel components for action/nav permission management.
5565
5567
  export { ActionPermissionsManager } from "./features/site-settings/components/ActionPermissionsManager";
5566
5568
  export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
@@ -1,18 +1,2 @@
1
- export interface AddressSeedData {
2
- id: string;
3
- label: string;
4
- fullName: string;
5
- phone: string;
6
- addressLine1: string;
7
- addressLine2?: string;
8
- landmark?: string;
9
- city: string;
10
- state: string;
11
- postalCode: string;
12
- country: string;
13
- isDefault: boolean;
14
- createdAt: Date;
15
- updatedAt: Date;
16
- userId: string;
17
- }
18
- export declare const addressesSeedData: AddressSeedData[];
1
+ import type { AddressDocument } from "../features/addresses/schemas/firestore";
2
+ export declare const addressesSeedData: AddressDocument[];