@mohasinac/appkit 4.1.1 → 4.2.0

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 (225) hide show
  1. package/dist/_internal/client/features/maintenance/index.d.ts +2 -0
  2. package/dist/_internal/client/features/maintenance/index.js +1 -0
  3. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.d.ts +9 -0
  4. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +55 -0
  5. package/dist/_internal/server/features/auctions/index.d.ts +1 -1
  6. package/dist/_internal/server/features/auctions/index.js +1 -1
  7. package/dist/_internal/server/features/auctions/service.js +2 -2
  8. package/dist/_internal/server/features/checkout/actions.d.ts +15 -0
  9. package/dist/_internal/server/features/checkout/actions.js +245 -182
  10. package/dist/_internal/server/features/maintenance/cloud-logs-data.d.ts +50 -0
  11. package/dist/_internal/server/features/maintenance/cloud-logs-data.js +152 -0
  12. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  13. package/dist/_internal/server/functions/scheduled.js +9 -1
  14. package/dist/_internal/server/jobs/core/jobRunners.js +10 -0
  15. package/dist/_internal/server/jobs/core/newsletterExport.d.ts +15 -0
  16. package/dist/_internal/server/jobs/core/newsletterExport.js +43 -0
  17. package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +4 -12
  18. package/dist/_internal/server/jobs/core/onOrderCreate.js +3 -3
  19. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +2 -0
  20. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +1 -0
  21. package/dist/_internal/server/jobs/core/onProductWrite.js +14 -2
  22. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +1 -0
  23. package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +1 -0
  24. package/dist/_internal/server/jobs/core/revenueRollup.d.ts +13 -0
  25. package/dist/_internal/server/jobs/core/revenueRollup.js +22 -0
  26. package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +35 -0
  27. package/dist/_internal/server/jobs/core/whatsappNotify.js +82 -0
  28. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  29. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  30. package/dist/_internal/server/jobs/handlers/revenueRollup.d.ts +2 -0
  31. package/dist/_internal/server/jobs/handlers/revenueRollup.js +2 -0
  32. package/dist/_internal/shared/features/auctions/config.d.ts +1 -1
  33. package/dist/_internal/shared/features/auctions/config.js +1 -1
  34. package/dist/_internal/shared/features/auctions/schema.js +1 -1
  35. package/dist/_internal/shared/features/cart/schema.js +2 -2
  36. package/dist/_internal/shared/features/checkout/config.d.ts +7 -0
  37. package/dist/_internal/shared/features/checkout/config.js +7 -0
  38. package/dist/_internal/shared/features/events/schema.js +1 -1
  39. package/dist/_internal/shared/features/orders/schema.js +1 -1
  40. package/dist/_internal/shared/features/products/schema.js +3 -3
  41. package/dist/_internal/shared/features/promotions/schema.js +3 -3
  42. package/dist/_internal/shared/fees/calculator.d.ts +32 -7
  43. package/dist/_internal/shared/fees/calculator.js +25 -0
  44. package/dist/client.d.ts +4 -4
  45. package/dist/client.js +4 -2
  46. package/dist/constants/api-endpoints.d.ts +9 -6
  47. package/dist/constants/api-endpoints.js +3 -2
  48. package/dist/contracts/client-payment-gateway.d.ts +1 -2
  49. package/dist/features/about/components/AboutView.d.ts +6 -16
  50. package/dist/features/about/components/AboutView.js +3 -3
  51. package/dist/features/about/components/FeesView.js +18 -0
  52. package/dist/features/about/index.d.ts +2 -1
  53. package/dist/features/about/schemas/firestore.d.ts +47 -0
  54. package/dist/features/about/schemas/firestore.js +6 -0
  55. package/dist/features/about/schemas/index.d.ts +210 -0
  56. package/dist/features/about/schemas/index.js +45 -0
  57. package/dist/features/account/hooks/useProfile.js +3 -0
  58. package/dist/features/admin/actions/notification-actions.d.ts +4 -1
  59. package/dist/features/admin/actions/notification-actions.js +56 -10
  60. package/dist/features/admin/components/AdminAdsView.js +1 -1
  61. package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +6 -0
  62. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +50 -0
  63. package/dist/features/admin/components/AdminCartsView.js +16 -3
  64. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  65. package/dist/features/admin/components/AdminCouponsView.js +14 -4
  66. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -42
  67. package/dist/features/admin/components/AdminMediaView.js +1 -1
  68. package/dist/features/admin/components/AdminNewsletterView.js +42 -11
  69. package/dist/features/admin/components/AdminNotificationsView.js +31 -19
  70. package/dist/features/admin/components/AdminOrdersView.js +7 -0
  71. package/dist/features/admin/components/AdminPayoutsView.js +18 -3
  72. package/dist/features/admin/components/AdminProductsView.js +17 -2
  73. package/dist/features/admin/components/AdminReviewsView.js +16 -2
  74. package/dist/features/admin/components/AdminScammersView.js +7 -0
  75. package/dist/features/admin/components/AdminSectionsView.js +4 -0
  76. package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
  77. package/dist/features/admin/components/AdminSiteSettingsView.js +127 -8
  78. package/dist/features/admin/components/AdminStoreEditorView.d.ts +2 -1
  79. package/dist/features/admin/components/AdminStoreEditorView.js +4 -4
  80. package/dist/features/admin/components/AdminStoresView.js +1 -1
  81. package/dist/features/admin/components/AdminSupportTicketDetailView.js +23 -5
  82. package/dist/features/admin/components/AdminSupportTicketsView.js +20 -2
  83. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +4 -1
  84. package/dist/features/admin/components/AdminTesterChecklistView.js +8 -0
  85. package/dist/features/admin/components/index.d.ts +2 -0
  86. package/dist/features/admin/components/index.js +1 -0
  87. package/dist/features/admin/constants/filter-tabs.d.ts +55 -41
  88. package/dist/features/admin/constants/filter-tabs.js +55 -27
  89. package/dist/features/admin/repository/analytics-rollup.repository.d.ts +25 -0
  90. package/dist/features/admin/repository/analytics-rollup.repository.js +31 -0
  91. package/dist/features/admin/repository/site-settings.repository.js +8 -1
  92. package/dist/features/admin/schemas/firestore.d.ts +46 -0
  93. package/dist/features/admin/schemas/firestore.js +62 -24
  94. package/dist/features/auctions/actions/bid-actions.js +1 -1
  95. package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
  96. package/dist/features/auctions/components/AuctionsListView.js +8 -1
  97. package/dist/features/auth/components/LoginForm.js +2 -2
  98. package/dist/features/auth/components/RegisterForm.js +2 -2
  99. package/dist/features/auth/permissions/constants.d.ts +16 -0
  100. package/dist/features/auth/permissions/constants.js +53 -0
  101. package/dist/features/auth/schemas/firestore.js +1 -0
  102. package/dist/features/blog/components/BlogFilters.js +1 -1
  103. package/dist/features/cart/schemas/firestore.d.ts +1 -1
  104. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  105. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  106. package/dist/features/events/components/EventFilters.js +2 -0
  107. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  108. package/dist/features/layout/BackToTop.d.ts +9 -5
  109. package/dist/features/layout/BackToTop.js +17 -21
  110. package/dist/features/layout/TitleBarLayout.d.ts +2 -2
  111. package/dist/features/layout/TitleBarLayout.js +4 -4
  112. package/dist/features/media/AvatarUpload.js +7 -3
  113. package/dist/features/media/MediaVideo.js +1 -1
  114. package/dist/features/media/finalize.d.ts +9 -13
  115. package/dist/features/media/finalize.js +23 -74
  116. package/dist/features/media/server.d.ts +1 -1
  117. package/dist/features/media/server.js +1 -1
  118. package/dist/features/orders/actions/refund-actions.js +1 -0
  119. package/dist/features/orders/hooks/useOrders.js +16 -4
  120. package/dist/features/orders/schemas/firestore.d.ts +19 -5
  121. package/dist/features/payments/schemas/firestore.d.ts +2 -2
  122. package/dist/features/pre-orders/components/PreOrdersListView.js +7 -0
  123. package/dist/features/products/components/ArtStickersListView.js +5 -0
  124. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -1
  125. package/dist/features/products/components/ProductForm.js +14 -1
  126. package/dist/features/products/components/ProductsIndexPageView.js +7 -0
  127. package/dist/features/products/constants/action-defs.d.ts +29 -3
  128. package/dist/features/products/constants/action-defs.js +77 -1
  129. package/dist/features/products/schemas/firestore.d.ts +1 -1
  130. package/dist/features/products/schemas/product-templates.d.ts +1 -1
  131. package/dist/features/products/types/index.d.ts +4 -0
  132. package/dist/features/scams/schemas/index.js +2 -2
  133. package/dist/features/search/components/Search.js +3 -3
  134. package/dist/features/seller/components/SellerAuctionsView.js +27 -2
  135. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  136. package/dist/features/seller/components/SellerPayoutsView.js +24 -10
  137. package/dist/features/seller/components/SellerPreOrdersView.js +12 -4
  138. package/dist/features/seller/components/SellerPrizeDrawsView.js +23 -5
  139. package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
  140. package/dist/features/seller/components/SellerProductShell.js +1 -1
  141. package/dist/features/seller/components/SellerProductsView.js +8 -6
  142. package/dist/features/seller/components/SellerReviewsView.js +27 -6
  143. package/dist/features/seller/components/index.d.ts +0 -2
  144. package/dist/features/seller/components/index.js +0 -1
  145. package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
  146. package/dist/features/stores/components/StoreProductsView.js +1 -1
  147. package/dist/features/stores/schemas/firestore.d.ts +11 -0
  148. package/dist/features/stores/schemas/firestore.js +5 -0
  149. package/dist/features/stores/schemas/index.d.ts +2 -2
  150. package/dist/features/tester/actions/checklist-item-actions.d.ts +6 -0
  151. package/dist/features/tester/actions/checklist-item-actions.js +2 -0
  152. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +13 -2
  153. package/dist/features/tester/components/AdminTesterFeedbackListView.js +2 -1
  154. package/dist/features/tester/components/AdminTesterFeedbackReportView.js +9 -5
  155. package/dist/features/tester/components/TesterHubView.js +34 -21
  156. package/dist/features/tester/repository/tester-checklist-item.repository.js +1 -0
  157. package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +18 -4
  158. package/dist/features/tester/repository/tester-checklist-response.repository.js +43 -8
  159. package/dist/features/tester/schemas/firestore.d.ts +8 -3
  160. package/dist/features/tester/schemas/firestore.js +6 -0
  161. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +21 -9
  162. package/dist/features/tester/utils/phases.d.ts +31 -0
  163. package/dist/features/tester/utils/phases.js +46 -0
  164. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
  165. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +10 -1
  166. package/dist/features/whatsapp-bot/helpers/whatsapp.js +47 -0
  167. package/dist/features/whatsapp-bot/types/index.d.ts +20 -1
  168. package/dist/features/wishlist/types/index.d.ts +3 -0
  169. package/dist/index.d.ts +15 -6
  170. package/dist/index.js +19 -9
  171. package/dist/next/components/NotFoundView.js +2 -1
  172. package/dist/next/routing/route-map.d.ts +6 -12
  173. package/dist/next/routing/route-map.js +3 -4
  174. package/dist/providers/db-firebase/admin.d.ts +1 -0
  175. package/dist/providers/db-firebase/admin.js +1 -1
  176. package/dist/repositories/index.d.ts +2 -0
  177. package/dist/repositories/index.js +1 -0
  178. package/dist/schemas/registry.d.ts +2 -2
  179. package/dist/seed/addresses-seed-data.js +18 -18
  180. package/dist/seed/bids-seed-data.js +4 -4
  181. package/dist/seed/blog-posts-seed-data.js +82 -82
  182. package/dist/seed/carousel-slides-seed-data.js +14 -10
  183. package/dist/seed/carousels-seed-data.js +3 -3
  184. package/dist/seed/cart-seed-data.js +92 -92
  185. package/dist/seed/claimed-coupons-seed-data.js +10 -10
  186. package/dist/seed/conversations-seed-data.js +75 -75
  187. package/dist/seed/coupon-usage-seed-data.js +12 -12
  188. package/dist/seed/coupons-seed-data.js +41 -41
  189. package/dist/seed/events-seed-data.js +105 -105
  190. package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
  191. package/dist/seed/grouped-listings-seed-data.js +79 -143
  192. package/dist/seed/history-seed-data.js +38 -38
  193. package/dist/seed/homepage-sections-seed-data.js +9 -9
  194. package/dist/seed/notifications-seed-data.js +56 -56
  195. package/dist/seed/offers-seed-data.js +91 -91
  196. package/dist/seed/orders-seed-data.js +121 -106
  197. package/dist/seed/payouts-seed-data.js +42 -42
  198. package/dist/seed/products-auctions-seed-data.js +10 -2
  199. package/dist/seed/products-standard-seed-data.js +40 -8
  200. package/dist/seed/reviews-seed-data.js +42 -23
  201. package/dist/seed/scammers-seed-data.js +22 -22
  202. package/dist/seed/sessions-seed-data.js +7 -7
  203. package/dist/seed/shipments-seed-data.js +10 -10
  204. package/dist/seed/site-settings-seed-data.js +89 -0
  205. package/dist/seed/store-addresses-seed-data.js +2 -2
  206. package/dist/seed/store-extensions-seed-data.js +93 -93
  207. package/dist/seed/stores-seed-data.js +2 -0
  208. package/dist/seed/support-tickets-seed-data.js +47 -47
  209. package/dist/seed/users-seed-data.js +55 -89
  210. package/dist/seed/wishlists-seed-data.js +22 -22
  211. package/dist/server.d.ts +4 -3
  212. package/dist/server.js +7 -7
  213. package/dist/styles.css +1 -1
  214. package/dist/tailwind-utilities.css +1 -1
  215. package/dist/ui/components/PageLoader.js +8 -3
  216. package/dist/ui/components/Select.d.ts +8 -1
  217. package/dist/ui/components/Select.js +2 -2
  218. package/dist/ui/components/SiteMark.d.ts +23 -0
  219. package/dist/ui/components/SiteMark.js +76 -0
  220. package/dist/ui/index.d.ts +2 -0
  221. package/dist/ui/index.js +1 -0
  222. package/dist/validation/schemas.d.ts +0 -2
  223. package/dist/validation/schemas.js +0 -2
  224. package/package.json +1 -1
  225. package/scripts/seed-cli.mjs +17 -15
@@ -17,7 +17,10 @@ export function AvatarUpload({ currentPhotoURL, currentCropData, userId, display
17
17
  readyToSave: labels?.readyToSave ?? "Ready to save",
18
18
  };
19
19
  const [previewUrl, setPreviewUrl] = useState(currentPhotoURL || null);
20
- const [cropData, setCropData] = useState(currentCropData || null);
20
+ const [cropData, setCropData] = useState(currentCropData ||
21
+ (currentPhotoURL
22
+ ? { url: currentPhotoURL, position: { x: 50, y: 50 }, zoom: 1 }
23
+ : null));
21
24
  const [tempImageUrl, setTempImageUrl] = useState(null);
22
25
  const [showCropModal, setShowCropModal] = useState(false);
23
26
  const [pendingFile, setPendingFile] = useState(null);
@@ -63,9 +66,10 @@ export function AvatarUpload({ currentPhotoURL, currentCropData, userId, display
63
66
  firstName,
64
67
  lastName,
65
68
  });
66
- await onUploadSuccess?.(downloadURL, pendingCropData);
69
+ const finalizedCropData = { ...pendingCropData, url: downloadURL };
70
+ await onUploadSuccess?.(downloadURL, finalizedCropData);
67
71
  setPreviewUrl(downloadURL);
68
- setCropData(pendingCropData);
72
+ setCropData(finalizedCropData);
69
73
  setPendingCropData(null);
70
74
  setPendingUploadFile(null);
71
75
  showToast("Avatar uploaded", "success");
@@ -38,7 +38,7 @@ export function MediaVideo({ src, thumbnailUrl, alt = "Video", controls = true,
38
38
  const { data: siteSettings } = useSiteSettings();
39
39
  const effectiveWatermark = watermark === null
40
40
  ? null
41
- : (watermark ?? siteSettings?.watermark ?? null);
41
+ : (watermark ?? siteSettings?.effectiveWatermark ?? siteSettings?.watermark ?? null);
42
42
  if (!resolvedSrc) {
43
43
  return (_jsx(Row
44
44
  // audit-color-pair-function-ok: deliberate faded placeholder-icon shade, not a readability regression
@@ -1,19 +1,15 @@
1
1
  import type { MediaField } from "./types";
2
2
  /**
3
- * Extract a storage object path from public/download URLs for the same bucket.
4
- */
5
- export declare function extractStoragePathFromUrl(url: string, bucketName: string): string | null;
6
- /**
7
- * Promote staged tmp/* uploads to canonical media/* path.
3
+ * Promote a staged tmp/* upload to its canonical media/* path.
8
4
  *
9
- * Handles two URL formats:
10
- * 1. `/media/{shortId}` the new SEO-friendly short-ID format.
11
- * Looks up the asset in the mediaAssets Firestore collection, moves the
12
- * file from tmp/ media/, updates the storagePath, and returns the same
13
- * URL unchanged (the URL is stable across the move).
14
- * 2. Raw GCS URLs (`https://storage.googleapis.com/...` or Firebase Storage URLs)
15
- * legacy path kept for backward compatibility; moves the file and returns a
16
- * /media/{finalStoragePath} proxy URL.
5
+ * Every producer of these URLs funnels through POST /api/media/finalize,
6
+ * which always returns a single-segment `/media/{shortId}` proxy URL (see
7
+ * that route's `downloadURL` construction) so that's the only shape this
8
+ * ever needs to handle. Looks up the asset in the mediaAssets Firestore
9
+ * collection, moves the file from tmp/ media/, updates the storagePath,
10
+ * and returns the same URL unchanged (the URL is stable across the move).
11
+ * Any other input (already-finalized `/media/...` path, or a URL that isn't
12
+ * a `/media/` proxy URL at all) is returned as-is — nothing to promote.
17
13
  */
18
14
  export declare function finalizeStagedMediaUrl(url: string): Promise<string>;
19
15
  export declare function finalizeStagedMediaField(url: string | null | undefined): Promise<string | undefined>;
@@ -1,35 +1,9 @@
1
1
  import { normalizeError } from "../../errors/normalize";
2
2
  import { getAdminStorage } from "../../providers/db-firebase";
3
- import { FIREBASE_STORAGE_HOST, GCS_HOST } from "../../utils/media-url";
4
3
  import { mediaAssetsRepository } from "./repository/media-assets.repository";
5
4
  const TMP_MEDIA_PREFIX = "tmp/";
6
5
  const FINAL_MEDIA_PREFIX = "media/";
7
6
  const PROXY_URL_PREFIX = "/media/";
8
- /**
9
- * Extract a storage object path from public/download URLs for the same bucket.
10
- */
11
- export function extractStoragePathFromUrl(url, bucketName) {
12
- try {
13
- const parsed = new URL(url);
14
- if (parsed.hostname === GCS_HOST) {
15
- const parts = parsed.pathname.split("/").filter(Boolean);
16
- if (parts.length >= 2 && parts[0] === bucketName) {
17
- return parts.slice(1).join("/");
18
- }
19
- }
20
- if (parsed.hostname === FIREBASE_STORAGE_HOST) {
21
- const match = parsed.pathname.match(/\/v0\/b\/([^/]+)\/o\/(.+)$/);
22
- if (match && match[1] === bucketName) {
23
- return decodeURIComponent(match[2]);
24
- }
25
- }
26
- return null;
27
- }
28
- catch (_err) {
29
- void normalizeError(_err);
30
- return null;
31
- }
32
- }
33
7
  /**
34
8
  * Move a file from tmp/ to media/ in Firebase Storage.
35
9
  * Returns the new storage path.
@@ -47,60 +21,35 @@ async function moveToFinalPath(sourcePath) {
47
21
  return destinationPath;
48
22
  }
49
23
  /**
50
- * Promote staged tmp/* uploads to canonical media/* path.
24
+ * Promote a staged tmp/* upload to its canonical media/* path.
51
25
  *
52
- * Handles two URL formats:
53
- * 1. `/media/{shortId}` the new SEO-friendly short-ID format.
54
- * Looks up the asset in the mediaAssets Firestore collection, moves the
55
- * file from tmp/ media/, updates the storagePath, and returns the same
56
- * URL unchanged (the URL is stable across the move).
57
- * 2. Raw GCS URLs (`https://storage.googleapis.com/...` or Firebase Storage URLs)
58
- * legacy path kept for backward compatibility; moves the file and returns a
59
- * /media/{finalStoragePath} proxy URL.
26
+ * Every producer of these URLs funnels through POST /api/media/finalize,
27
+ * which always returns a single-segment `/media/{shortId}` proxy URL (see
28
+ * that route's `downloadURL` construction) so that's the only shape this
29
+ * ever needs to handle. Looks up the asset in the mediaAssets Firestore
30
+ * collection, moves the file from tmp/ media/, updates the storagePath,
31
+ * and returns the same URL unchanged (the URL is stable across the move).
32
+ * Any other input (already-finalized `/media/...` path, or a URL that isn't
33
+ * a `/media/` proxy URL at all) is returned as-is — nothing to promote.
60
34
  */
61
35
  export async function finalizeStagedMediaUrl(url) {
62
- // ── Path 1: /media/{shortId} proxy URLs (new system) ──────────────────────
63
- if (url.startsWith(PROXY_URL_PREFIX)) {
64
- const afterPrefix = url.slice(PROXY_URL_PREFIX.length);
65
- // Single-segment = shortId. Multi-segment = legacy raw path embedded in URL.
66
- if (!afterPrefix.includes("/")) {
67
- const shortId = afterPrefix;
68
- try {
69
- const asset = await mediaAssetsRepository.findById(shortId);
70
- if (asset && asset.status === "staged" && asset.storagePath.startsWith(TMP_MEDIA_PREFIX)) {
71
- const finalPath = await moveToFinalPath(asset.storagePath);
72
- await mediaAssetsRepository.promoteToFinalized(shortId, finalPath);
73
- }
74
- }
75
- catch (_err) {
76
- void normalizeError(_err);
77
- // Non-fatal: URL is still valid; proxy will serve whatever storagePath points to.
78
- }
79
- return url; // URL is stable — same before and after the file move
80
- }
81
- // Multi-segment legacy: /media/tmp/folder/uid/file.jpg → move + return proxy URL
82
- const rawPath = afterPrefix;
83
- if (rawPath.startsWith(TMP_MEDIA_PREFIX)) {
84
- try {
85
- const finalPath = await moveToFinalPath(rawPath);
86
- return `${PROXY_URL_PREFIX}${finalPath}`;
87
- }
88
- catch (_err) {
89
- void normalizeError(_err);
90
- return url;
91
- }
36
+ if (!url.startsWith(PROXY_URL_PREFIX))
37
+ return url;
38
+ const shortId = url.slice(PROXY_URL_PREFIX.length);
39
+ if (shortId.includes("/"))
40
+ return url; // not a shortId — nothing to promote
41
+ try {
42
+ const asset = await mediaAssetsRepository.findById(shortId);
43
+ if (asset && asset.status === "staged" && asset.storagePath.startsWith(TMP_MEDIA_PREFIX)) {
44
+ const finalPath = await moveToFinalPath(asset.storagePath);
45
+ await mediaAssetsRepository.promoteToFinalized(shortId, finalPath);
92
46
  }
93
- return url; // already at media/ or other path — no-op
94
47
  }
95
- // ── Path 2: Legacy raw GCS URLs ────────────────────────────────────────────
96
- const storage = getAdminStorage();
97
- const bucket = storage.bucket();
98
- const sourcePath = extractStoragePathFromUrl(url, bucket.name);
99
- if (!sourcePath || !sourcePath.startsWith(TMP_MEDIA_PREFIX)) {
100
- return url;
48
+ catch (_err) {
49
+ void normalizeError(_err);
50
+ // Non-fatal: URL is still valid; proxy will serve whatever storagePath points to.
101
51
  }
102
- const finalPath = await moveToFinalPath(sourcePath);
103
- return `${PROXY_URL_PREFIX}${finalPath}`;
52
+ return url; // URL is stable — same before and after the file move
104
53
  }
105
54
  export async function finalizeStagedMediaField(url) {
106
55
  if (!url)
@@ -1 +1 @@
1
- export { extractStoragePathFromUrl, finalizeStagedMediaUrl, finalizeStagedMediaField, finalizeStagedMediaArray, finalizeStagedMediaObject, finalizeStagedMediaObjectArray, } from "./finalize";
1
+ export { finalizeStagedMediaUrl, finalizeStagedMediaField, finalizeStagedMediaArray, finalizeStagedMediaObject, finalizeStagedMediaObjectArray, } from "./finalize";
@@ -1 +1 @@
1
- export { extractStoragePathFromUrl, finalizeStagedMediaUrl, finalizeStagedMediaField, finalizeStagedMediaArray, finalizeStagedMediaObject, finalizeStagedMediaObjectArray, } from "./finalize";
1
+ export { finalizeStagedMediaUrl, finalizeStagedMediaField, finalizeStagedMediaArray, finalizeStagedMediaObject, finalizeStagedMediaObjectArray, } from "./finalize";
@@ -49,6 +49,7 @@ export async function issuePartialRefund(adminUid, orderId, deductFees, refundNo
49
49
  : `Your full refund of ₹${grossRefund} is being processed.`,
50
50
  relatedId: orderId,
51
51
  relatedType: "order",
52
+ orderWhatsappAddonPaid: order.whatsappNotifyAddon === true,
52
53
  });
53
54
  serverLogger.info("Admin partial refund initiated", {
54
55
  adminUid,
@@ -1,12 +1,17 @@
1
1
  import { useQuery } from "@tanstack/react-query";
2
2
  import { apiClient } from "../../../http";
3
- import { ORDER_ENDPOINTS } from "../../../constants/api-endpoints";
3
+ import { ORDER_ENDPOINTS, ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints";
4
4
  export function useOrders(params = {}, opts) {
5
5
  const sp = new URLSearchParams();
6
6
  if (params.userId)
7
7
  sp.set("userId", params.userId);
8
+ // Wire key is "status", not "orderStatus" — matches what /api/user/orders
9
+ // (the only real handler backing this hook's default endpoint) reads via
10
+ // getStringParam(searchParams, "status"). The OrderListParams prop stays
11
+ // named `orderStatus` since existing call sites pass it that way; only the
12
+ // serialized query-string key changes.
8
13
  if (params.orderStatus)
9
- sp.set("orderStatus", params.orderStatus);
14
+ sp.set("status", params.orderStatus);
10
15
  if (params.paymentStatus)
11
16
  sp.set("paymentStatus", params.paymentStatus);
12
17
  if (params.sort)
@@ -16,7 +21,10 @@ export function useOrders(params = {}, opts) {
16
21
  if (params.perPage)
17
22
  sp.set("perPage", String(params.perPage));
18
23
  const qs = sp.toString();
19
- const endpoint = opts?.endpoint ?? `${ORDER_ENDPOINTS.LIST}${qs ? `?${qs}` : ""}`;
24
+ // ORDER_ENDPOINTS.LIST ("/api/orders") has no GET route handler every
25
+ // real caller of this hook wants the current user's own orders, served by
26
+ // /api/user/orders. Default here, not ORDER_ENDPOINTS.LIST.
27
+ const endpoint = opts?.endpoint ?? `${ACCOUNT_ENDPOINTS.ORDERS}${qs ? `?${qs}` : ""}`;
20
28
  const query = useQuery({
21
29
  queryKey: ["orders", qs],
22
30
  queryFn: () => apiClient.get(endpoint),
@@ -32,7 +40,11 @@ export function useOrders(params = {}, opts) {
32
40
  };
33
41
  }
34
42
  export function useOrder(id, opts) {
35
- const endpoint = opts?.endpoint ?? ORDER_ENDPOINTS.BY_ID(id);
43
+ // Same fix as useOrders() above — ORDER_ENDPOINTS.BY_ID ("/api/orders/{id}")
44
+ // has no route.ts handler (only [id]/code, [id]/invoice, [id]/payment-proof,
45
+ // [id]/refund, [id]/dispute subroutes exist). The real single-order handler
46
+ // for the current user is /api/user/orders/[id].
47
+ const endpoint = opts?.endpoint ?? ACCOUNT_ENDPOINTS.ORDER_BY_ID(id);
36
48
  const query = useQuery({
37
49
  queryKey: ["orders", id],
38
50
  queryFn: () => apiClient.get(endpoint),
@@ -63,7 +63,7 @@ export interface EmiInstallment {
63
63
  /** 1-based installment number. */
64
64
  index: number;
65
65
  dueDate: Date;
66
- /** Installment amount in paise (principal share + surcharge share for this installment). */
66
+ /** Installment amount in decimal rupees (principal share + surcharge share for this installment). */
67
67
  amount: number;
68
68
  status: EmiInstallmentStatus;
69
69
  paidAt?: Date;
@@ -116,7 +116,7 @@ export interface OrderDocumentItem {
116
116
  export interface OrderRefundEvent {
117
117
  refundId: string;
118
118
  type: RefundType;
119
- /** Amount in paise. */
119
+ /** Amount in decimal rupees. */
120
120
  amount: number;
121
121
  /** ProductIds / itemIds that were refunded (for partial refunds). */
122
122
  itemIds?: string[];
@@ -183,6 +183,20 @@ export interface OrderDocument extends BaseDocument {
183
183
  codRemainingAmount?: number;
184
184
  /** COD handling fee charged to the buyer: max(codHandlingFeeMin, subtotal × codHandlingFeePercent / 100). Only set when paymentMethod === "cod". */
185
185
  codHandlingFee?: number;
186
+ /** Buyer opted into WhatsApp order-update messages at checkout (unchecked by default). */
187
+ whatsappNotifyAddon?: boolean;
188
+ /** Fee charged for the WhatsApp addon, decimal rupees — snapshot of siteSettings.commissions.whatsappNotifyFee at order time. */
189
+ whatsappNotifyFee?: number;
190
+ /** Buyer opted into gift wrapping at checkout (unchecked by default). */
191
+ giftWrapAddon?: boolean;
192
+ /** Fee charged for gift wrap, decimal rupees — snapshot of siteSettings.commissions.giftWrapFee at order time. */
193
+ giftWrapFee?: number;
194
+ /** Optional buyer-written gift message, shown to the seller for fulfilment. Capped length. */
195
+ giftWrapMessage?: string;
196
+ /** Buyer opted into shipment protection (loss/damage insurance) at checkout (unchecked by default). */
197
+ shipmentProtectionAddon?: boolean;
198
+ /** Fee charged for shipment protection, decimal rupees — snapshot of siteSettings.commissions.shipmentProtectionFeePercent/Min at order time. */
199
+ shipmentProtectionFee?: number;
186
200
  /** Order subtotal before GST — the amount GST is computed on. */
187
201
  taxableAmount?: number;
188
202
  /** Total GST charged (cgst + sgst, or igst — never both pairs at once). */
@@ -195,12 +209,12 @@ export interface OrderDocument extends BaseDocument {
195
209
  emiEnabled?: boolean;
196
210
  /** Number of monthly installments the buyer chose (2–6). */
197
211
  emiTenureMonths?: number;
198
- /** Down payment collected at checkout, in paise (emiTokenPercent × seller subtotal). */
212
+ /** Down payment collected at checkout, in decimal rupees (emiTokenPercent × seller subtotal). */
199
213
  emiTokenAmount?: number;
200
- /** Extra cost of choosing EMI over full payment, in paise — split between platform and seller. */
214
+ /** Extra cost of choosing EMI over full payment, in decimal rupees — split between platform and seller. */
201
215
  emiSurchargeAmount?: number;
202
216
  emiInstallments?: EmiInstallment[];
203
- /** Sum of unpaid installment amounts, in paise. 0 once all installments are paid. */
217
+ /** Sum of unpaid installment amounts, in decimal rupees. 0 once all installments are paid. */
204
218
  emiRemainingBalance?: number;
205
219
  /** True once every installment's status is "paid". Gates shipment unless the product's `allowShipBeforeEmiComplete` flag is set. */
206
220
  emiComplete?: boolean;
@@ -19,9 +19,9 @@ export type PayoutStatus = "pending" | "processing" | "paid" | "failed";
19
19
  export interface PayoutRefundDeduction {
20
20
  orderId: string;
21
21
  refundId: string;
22
- /** Gross refund amount in paise (for audit trail). */
22
+ /** Gross refund amount in decimal rupees (for audit trail). */
23
23
  refundedAmount: number;
24
- /** Net amount deducted from the seller payout in paise. */
24
+ /** Net amount deducted from the seller payout in decimal rupees. */
25
25
  deductedAmount: number;
26
26
  reason: string;
27
27
  appliedAt: Date;
@@ -26,6 +26,13 @@ function buildPreOrderFilters(params) {
26
26
  const preOrderProductionStatus = sp(params, "preOrderProductionStatus");
27
27
  if (preOrderProductionStatus)
28
28
  parts.push(sieveFilter("preOrderProductionStatus", SIEVE_OP.EQ, preOrderProductionStatus));
29
+ // Mirror PreOrdersIndexListing's client-side default (same Root Cause pattern as
30
+ // auctions' dateFrom default — SSR initialData is seeded into React Query with
31
+ // staleTime:Infinity, so if this filter doesn't already exclude closed/out-of-stock
32
+ // pre-orders, the client never refetches and they leak into the default view).
33
+ const showClosed = sp(params, "showClosed") === "true";
34
+ if (!showClosed)
35
+ parts.push(sieveFilter("stockQuantity", SIEVE_OP.GT, 0));
29
36
  return parts.join(",");
30
37
  }
31
38
  export async function PreOrdersListView({ searchParams = {} }) {
@@ -42,6 +42,11 @@ function buildArtStickersFilters(params) {
42
42
  const storeId = sp(params, "seller");
43
43
  if (storeId)
44
44
  parts.push(sieveFilter(PRODUCT_FIELDS.STORE_ID, SIEVE_OP.EQ, storeId));
45
+ // Mirror ProductsIndexListing's client-side "Show sold" default — see
46
+ // ProductsIndexPageView.tsx's buildProductFilters for the full explanation.
47
+ const showSold = sp(params, "showSold") === "true";
48
+ if (!showSold)
49
+ parts.push(sieveFilter(PRODUCT_FIELDS.STOCK_QUANTITY, SIEVE_OP.GT, 0));
45
50
  return sieveAnd(...parts);
46
51
  }
47
52
  export async function ArtStickersListView({ searchParams = {} }) {
@@ -44,7 +44,13 @@ export interface ProductDetailPageViewProps {
44
44
  productFeatures?: ProductFeatureDocument[];
45
45
  /** Site-wide COD availability (`siteSettings.payment.codEnabled`), threaded from the page's data layer. Drives the "Cash on Delivery" feature badge. */
46
46
  codEnabled?: boolean;
47
- /** Site-wide EMI availability (`siteSettings.emi.enabled`), threaded from the page's data layer. Drives the "EMI Available" feature badge. */
47
+ /**
48
+ * Fully-resolved EMI eligibility for this product — site-wide flag AND the
49
+ * seller's `StoreDocument.emiEnabled` opt-in AND price above
50
+ * `siteSettings.emi.minOrderValue`, computed by the page's data layer
51
+ * (mirrors `checkEmiEligibility()`'s checkout-time rule). Drives the "EMI
52
+ * Available" feature badge.
53
+ */
48
54
  emiEnabled?: boolean;
49
55
  }
50
56
  export declare function ProductDetailPageView({ slug, initialProduct, renderOfferAction, renderPrimaryActions, productFeatures, codEnabled, emiEnabled, }: ProductDetailPageViewProps): Promise<import("react").JSX.Element>;
@@ -132,7 +132,20 @@ export function ProductForm({ product, onChange, isReadonly = false, renderDescr
132
132
  thumbnailUrl: media.thumbnailUrl,
133
133
  },
134
134
  });
135
- }, onUpload: handleVideoUpload, accept: "video/*", maxSizeMB: 50, helperText: t("formVideoHelper"), onAbort: onMediaAbort })), _jsx(TagInput, { label: t("formTags"), value: product.tags || [], onChange: (tags) => update({ tags }), disabled: isReadonly, placeholder: t("formTagsPlaceholder") }), _jsxs(FormGroup, { columns: 2, children: [_jsx(Checkbox, { label: t("formFeatured"), checked: !!product.featured, onChange: (e) => update({ featured: e.target.checked }), disabled: isReadonly }), _jsx(Checkbox, { label: t("formIsPromoted"), checked: !!product.isPromoted, onChange: (e) => update({ isPromoted: e.target.checked }), disabled: isReadonly }), _jsx(Checkbox, { label: t("formAllowShipBeforeEmiComplete"), checked: !!product.allowShipBeforeEmiComplete, onChange: (e) => update({ allowShipBeforeEmiComplete: e.target.checked }), disabled: isReadonly })] }), _jsx(Heading, { level: 4, className: "mt-4", children: t("sectionConditionShipping") }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "condition", label: t("formCondition"), type: "select", value: product.condition || "new", onChange: (value) => update({
135
+ }, onUpload: handleVideoUpload, accept: "video/*", maxSizeMB: 50, helperText: t("formVideoHelper"), onAbort: onMediaAbort })), _jsx(TagInput, { label: t("formTags"), value: product.tags || [], onChange: (tags) => update({ tags }), disabled: isReadonly, placeholder: t("formTagsPlaceholder") }), _jsxs(FormGroup, { columns: 2, children: [_jsx(Checkbox, { label: t("formFeatured"), checked: !!product.featured, onChange: (e) => update({ featured: e.target.checked }), disabled: isReadonly }), _jsx(Checkbox, { label: t("formIsPromoted"), checked: !!product.isPromoted, onChange: (e) => update({ isPromoted: e.target.checked }), disabled: isReadonly }), _jsx(Checkbox, { label: t("formAllowShipBeforeEmiComplete"), checked: !!product.allowShipBeforeEmiComplete, onChange: (e) => update({ allowShipBeforeEmiComplete: e.target.checked }), disabled: isReadonly }), _jsx(Checkbox, { label: t("formAllowOffers"), checked: !!product.allowOffers, onChange: (e) => update({
136
+ allowOffers: e.target.checked,
137
+ minOfferPercent: e.target.checked ? product.minOfferPercent ?? 50 : undefined,
138
+ }), disabled: isReadonly })] }), product.allowOffers && (_jsxs(_Fragment, { children: [_jsx(Alert, { variant: "info", title: t("formAllowOffersHelp"), children: t("formAllowOffersHelp") }), _jsx(FormField, { name: "minOfferPercent", label: t("formMinOfferPercent"), type: "number", value: String(product.minOfferPercent ?? ""), onChange: (value) => update({ minOfferPercent: Number(value) }), disabled: isReadonly, placeholder: "50" })] })), _jsx(Heading, { level: 4, className: "mt-4", children: t("sectionTaxGst") }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "gstRate", label: t("formGstRate"), type: "select",
139
+ // Unset is semantically "exempt" (see ProductDocument.gstRate JSDoc),
140
+ // same as 0% — default the control to 0 so the select stays a fixed
141
+ // 5-option enum instead of adding a 6th "unset" placeholder entry.
142
+ value: String(product.gstRate ?? 0), onChange: (value) => update({ gstRate: Number(value) }), disabled: isReadonly, options: [
143
+ { value: "0", label: "0%" },
144
+ { value: "5", label: "5%" },
145
+ { value: "12", label: "12%" },
146
+ { value: "18", label: "18%" },
147
+ { value: "28", label: "28%" },
148
+ ] }), _jsx(FormField, { name: "hsnCode", label: t("formHsnCode"), type: "text", value: product.hsnCode ?? "", onChange: (value) => update({ hsnCode: value }), disabled: isReadonly, placeholder: "e.g. 9503" })] }), _jsx(Heading, { level: 4, className: "mt-4", children: t("sectionConditionShipping") }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "condition", label: t("formCondition"), type: "select", value: product.condition || "new", onChange: (value) => update({
136
149
  condition: value,
137
150
  }), disabled: isReadonly, options: [
138
151
  { value: "new", label: t("formConditionNew") },
@@ -47,6 +47,13 @@ function buildProductFilters(params) {
47
47
  if (freeShipping === "true") {
48
48
  parts.push(sieveFilter(PRODUCT_FIELDS.SHIPPING_PAID_BY, SIEVE_OP.EQ, PRODUCT_FIELDS.SHIPPING_PAID_BY_VALUES.SELLER));
49
49
  }
50
+ // Mirror ProductsIndexListing's client-side "Show sold" default (same Root Cause
51
+ // pattern as auctions' dateFrom default — SSR initialData is seeded into React
52
+ // Query with staleTime:Infinity, so if this filter doesn't already exclude sold /
53
+ // out-of-stock products, the client never refetches and they leak into the default view).
54
+ const showSold = sp(params, "showSold") === "true";
55
+ if (!showSold)
56
+ parts.push(sieveFilter(PRODUCT_FIELDS.STOCK_QUANTITY, SIEVE_OP.GT, 0));
50
57
  return sieveAnd(...parts);
51
58
  }
52
59
  export async function ProductsIndexPageView({ searchParams = {} }) {
@@ -280,15 +280,40 @@ export declare const DASHBOARD_QUICK_ACTION_ID: {
280
280
  readonly ADMIN_ADD_BLOG: "dqa-admin-add-blog";
281
281
  readonly ADMIN_ADD_FAQ: "dqa-admin-add-faq";
282
282
  readonly ADMIN_SETTINGS: "dqa-admin-settings";
283
+ readonly ADMIN_STORES: "dqa-admin-stores";
284
+ readonly ADMIN_ORDERS: "dqa-admin-orders";
285
+ readonly ADMIN_PAYOUTS: "dqa-admin-payouts";
286
+ readonly ADMIN_ANALYTICS: "dqa-admin-analytics";
287
+ readonly ADMIN_EVENTS: "dqa-admin-events";
288
+ readonly ADMIN_SUPPORT: "dqa-admin-support";
289
+ readonly ADMIN_MODERATION: "dqa-admin-moderation";
290
+ readonly ADMIN_INTEGRATION_GUIDES: "dqa-admin-integration-guides";
291
+ readonly ADMIN_USERS: "dqa-admin-users";
292
+ readonly ADMIN_CATEGORIES: "dqa-admin-categories";
293
+ readonly ADMIN_REVIEWS: "dqa-admin-reviews";
294
+ readonly ADMIN_FAQS: "dqa-admin-faqs";
295
+ readonly ADMIN_CAROUSEL: "dqa-admin-carousel";
296
+ readonly ADMIN_SECTIONS: "dqa-admin-sections";
283
297
  readonly SELLER_ADD_PRODUCT: "dqa-seller-add-product";
284
298
  readonly SELLER_ADD_COUPON: "dqa-seller-add-coupon";
285
299
  readonly SELLER_VIEW_ORDERS: "dqa-seller-view-orders";
286
300
  readonly SELLER_PAYOUT_REQ: "dqa-seller-payout-request";
287
301
  readonly SELLER_SETTINGS: "dqa-seller-settings";
302
+ readonly SELLER_AUCTIONS: "dqa-seller-auctions";
303
+ readonly SELLER_SHIPPING: "dqa-seller-shipping";
304
+ readonly SELLER_MESSAGES: "dqa-seller-messages";
305
+ readonly SELLER_WHATSAPP: "dqa-seller-whatsapp";
306
+ readonly SELLER_REVIEWS: "dqa-seller-reviews";
307
+ readonly SELLER_PRODUCTS: "dqa-seller-products";
308
+ readonly SELLER_STOREFRONT: "dqa-seller-storefront";
309
+ readonly SELLER_ANALYTICS: "dqa-seller-analytics";
288
310
  readonly USER_VIEW_ORDERS: "dqa-user-view-orders";
289
311
  readonly USER_VIEW_WISHLIST: "dqa-user-view-wishlist";
290
312
  readonly USER_EDIT_PROFILE: "dqa-user-edit-profile";
291
313
  readonly USER_ADD_ADDRESS: "dqa-user-add-address";
314
+ readonly USER_RECENTLY_VIEWED: "dqa-user-recently-viewed";
315
+ readonly USER_MY_CATALOGUE: "dqa-user-my-catalogue";
316
+ readonly USER_MY_COUPONS: "dqa-user-my-coupons";
292
317
  };
293
318
  export type DashboardQuickActionId = (typeof DASHBOARD_QUICK_ACTION_ID)[keyof typeof DASHBOARD_QUICK_ACTION_ID];
294
319
  export interface DashboardQuickActionMeta {
@@ -309,9 +334,9 @@ export interface DashboardQuickActionMeta {
309
334
  }
310
335
  export declare const DASHBOARD_QUICK_ACTION_META: Record<DashboardQuickActionId, DashboardQuickActionMeta>;
311
336
  export declare const DASHBOARD_QUICK_ACTIONS: {
312
- readonly admin: readonly ["dqa-admin-add-product", "dqa-admin-add-user", "dqa-admin-add-store", "dqa-admin-add-coupon", "dqa-admin-add-event", "dqa-admin-add-blog", "dqa-admin-settings"];
313
- readonly seller: readonly ["dqa-seller-add-product", "dqa-seller-add-coupon", "dqa-seller-view-orders", "dqa-seller-payout-request", "dqa-seller-settings"];
314
- readonly user: readonly ["dqa-user-view-orders", "dqa-user-view-wishlist", "dqa-user-edit-profile", "dqa-user-add-address"];
337
+ readonly admin: readonly ["dqa-admin-add-product", "dqa-admin-add-user", "dqa-admin-add-store", "dqa-admin-add-coupon", "dqa-admin-add-event", "dqa-admin-add-blog", "dqa-admin-users", "dqa-admin-stores", "dqa-admin-orders", "dqa-admin-payouts", "dqa-admin-analytics", "dqa-admin-categories", "dqa-admin-reviews", "dqa-admin-events", "dqa-admin-faqs", "dqa-admin-carousel", "dqa-admin-sections", "dqa-admin-support", "dqa-admin-moderation", "dqa-admin-integration-guides", "dqa-admin-settings"];
338
+ readonly seller: readonly ["dqa-seller-add-product", "dqa-seller-products", "dqa-seller-view-orders", "dqa-seller-analytics", "dqa-seller-add-coupon", "dqa-seller-auctions", "dqa-seller-payout-request", "dqa-seller-shipping", "dqa-seller-messages", "dqa-seller-whatsapp", "dqa-seller-reviews", "dqa-seller-storefront", "dqa-seller-settings"];
339
+ readonly user: readonly ["dqa-user-view-orders", "dqa-user-view-wishlist", "dqa-user-edit-profile", "dqa-user-add-address", "dqa-user-recently-viewed", "dqa-user-my-catalogue", "dqa-user-my-coupons"];
315
340
  };
316
341
  export declare const ADMIN_BULK_ACTIONS: {
317
342
  readonly users: readonly ["row-manage", "row-suspend", "row-restore", "row-delete"];
@@ -350,6 +375,7 @@ export declare const ADMIN_BULK_ACTIONS: {
350
375
  };
351
376
  export declare const SELLER_BULK_ACTIONS: {
352
377
  readonly products: readonly ["row-publish", "row-archive", "row-delete"];
378
+ readonly payouts: readonly ["row-export"];
353
379
  readonly coupons: readonly ["row-archive", "row-delete"];
354
380
  readonly bids: readonly ["row-cancel"];
355
381
  readonly bundles: readonly ["row-delete"];
@@ -351,17 +351,42 @@ export const DASHBOARD_QUICK_ACTION_ID = {
351
351
  ADMIN_ADD_BLOG: "dqa-admin-add-blog",
352
352
  ADMIN_ADD_FAQ: "dqa-admin-add-faq",
353
353
  ADMIN_SETTINGS: "dqa-admin-settings",
354
+ ADMIN_STORES: "dqa-admin-stores",
355
+ ADMIN_ORDERS: "dqa-admin-orders",
356
+ ADMIN_PAYOUTS: "dqa-admin-payouts",
357
+ ADMIN_ANALYTICS: "dqa-admin-analytics",
358
+ ADMIN_EVENTS: "dqa-admin-events",
359
+ ADMIN_SUPPORT: "dqa-admin-support",
360
+ ADMIN_MODERATION: "dqa-admin-moderation",
361
+ ADMIN_INTEGRATION_GUIDES: "dqa-admin-integration-guides",
362
+ ADMIN_USERS: "dqa-admin-users",
363
+ ADMIN_CATEGORIES: "dqa-admin-categories",
364
+ ADMIN_REVIEWS: "dqa-admin-reviews",
365
+ ADMIN_FAQS: "dqa-admin-faqs",
366
+ ADMIN_CAROUSEL: "dqa-admin-carousel",
367
+ ADMIN_SECTIONS: "dqa-admin-sections",
354
368
  // Seller / Store
355
369
  SELLER_ADD_PRODUCT: "dqa-seller-add-product",
356
370
  SELLER_ADD_COUPON: "dqa-seller-add-coupon",
357
371
  SELLER_VIEW_ORDERS: "dqa-seller-view-orders",
358
372
  SELLER_PAYOUT_REQ: "dqa-seller-payout-request",
359
373
  SELLER_SETTINGS: "dqa-seller-settings",
374
+ SELLER_AUCTIONS: "dqa-seller-auctions",
375
+ SELLER_SHIPPING: "dqa-seller-shipping",
376
+ SELLER_MESSAGES: "dqa-seller-messages",
377
+ SELLER_WHATSAPP: "dqa-seller-whatsapp",
378
+ SELLER_REVIEWS: "dqa-seller-reviews",
379
+ SELLER_PRODUCTS: "dqa-seller-products",
380
+ SELLER_STOREFRONT: "dqa-seller-storefront",
381
+ SELLER_ANALYTICS: "dqa-seller-analytics",
360
382
  // User / Buyer
361
383
  USER_VIEW_ORDERS: "dqa-user-view-orders",
362
384
  USER_VIEW_WISHLIST: "dqa-user-view-wishlist",
363
385
  USER_EDIT_PROFILE: "dqa-user-edit-profile",
364
386
  USER_ADD_ADDRESS: "dqa-user-add-address",
387
+ USER_RECENTLY_VIEWED: "dqa-user-recently-viewed",
388
+ USER_MY_CATALOGUE: "dqa-user-my-catalogue",
389
+ USER_MY_COUPONS: "dqa-user-my-coupons",
365
390
  };
366
391
  export const DASHBOARD_QUICK_ACTION_META = {
367
392
  [DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT, label: "Add Product", variant: "primary", iconName: "Plus", requiresAuth: true, requiredRole: "admin", requiredPermission: "products.create" },
@@ -372,15 +397,40 @@ export const DASHBOARD_QUICK_ACTION_META = {
372
397
  [DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG, label: "New Post", variant: "outline", iconName: "FileText", requiresAuth: true, requiredRole: "admin", requiredPermission: "blog.create" },
373
398
  [DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ, label: "Add FAQ", variant: "outline", iconName: "HelpCircle", requiresAuth: true, requiredRole: "admin", requiredPermission: "faqs.create" },
374
399
  [DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS, label: "Settings", variant: "ghost", iconName: "Settings", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.settings.read" },
400
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_STORES]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_STORES, label: "Stores", variant: "outline", iconName: "Store", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.stores.read" },
401
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ORDERS, label: "Orders", variant: "outline", iconName: "ShoppingBag", requiresAuth: true, requiredRole: "admin", requiredPermission: "orders.read" },
402
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_PAYOUTS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_PAYOUTS, label: "Payouts", variant: "outline", iconName: "Banknote", requiresAuth: true, requiredRole: "admin", requiredPermission: "payouts.read" },
403
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_ANALYTICS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ANALYTICS, label: "Analytics", variant: "outline", iconName: "BarChart", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.analytics.read" },
404
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_EVENTS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_EVENTS, label: "Events", variant: "outline", iconName: "Calendar", requiresAuth: true, requiredRole: "admin", requiredPermission: "events.read" },
405
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_SUPPORT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_SUPPORT, label: "Support Tickets", variant: "outline", iconName: "LifeBuoy", requiresAuth: true, requiredRole: "admin", requiredPermission: "support.read" },
406
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_MODERATION]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_MODERATION, label: "Moderation", variant: "outline", iconName: "ShieldAlert", requiresAuth: true, requiredRole: "admin", requiredPermission: "moderation.read" },
407
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_INTEGRATION_GUIDES]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_INTEGRATION_GUIDES, label: "Integration Guides", variant: "ghost", iconName: "BookOpen", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin:site:read" },
408
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_USERS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_USERS, label: "Users", variant: "outline", iconName: "Users", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.users.read" },
409
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_CATEGORIES]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_CATEGORIES, label: "Categories", variant: "outline", iconName: "Tag", requiresAuth: true, requiredRole: "admin", requiredPermission: "categories.read" },
410
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_REVIEWS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_REVIEWS, label: "Reviews", variant: "outline", iconName: "Star", requiresAuth: true, requiredRole: "admin", requiredPermission: "reviews.read" },
411
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_FAQS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_FAQS, label: "FAQs", variant: "outline", iconName: "HelpCircle", requiresAuth: true, requiredRole: "admin", requiredPermission: "faqs.read" },
412
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_CAROUSEL]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_CAROUSEL, label: "Carousel", variant: "outline", iconName: "Layout", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.settings.read" },
413
+ [DASHBOARD_QUICK_ACTION_ID.ADMIN_SECTIONS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_SECTIONS, label: "Sections", variant: "outline", iconName: "Layers", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.settings.read" },
375
414
  [DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT, label: "List a Product", variant: "primary", iconName: "Plus", requiresAuth: true, requiredRole: "seller", requiredPermission: "products.create" },
376
415
  [DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON, label: "New Coupon", variant: "outline", iconName: "Tag", requiresAuth: true, requiredRole: "seller", requiredPermission: "coupons.create" },
377
416
  [DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS, label: "Orders", variant: "outline", iconName: "ShoppingBag", requiresAuth: true, requiredRole: "seller" },
378
417
  [DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ, label: "Request Payout", variant: "outline", iconName: "Banknote", requiresAuth: true, requiredRole: "seller", requiredPermission: "seller.payouts.request" },
379
418
  [DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS, label: "Store Settings", variant: "ghost", iconName: "Settings", requiresAuth: true, requiredRole: "seller" },
419
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_AUCTIONS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_AUCTIONS, label: "Auctions", variant: "outline", iconName: "Gavel", requiresAuth: true, requiredRole: "seller" },
420
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_SHIPPING]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_SHIPPING, label: "Shipping", variant: "outline", iconName: "Truck", requiresAuth: true, requiredRole: "seller" },
421
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_MESSAGES]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_MESSAGES, label: "Messages", variant: "outline", iconName: "MessageCircle", requiresAuth: true, requiredRole: "seller" },
422
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_WHATSAPP]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_WHATSAPP, label: "WhatsApp", variant: "outline", iconName: "Phone", requiresAuth: true, requiredRole: "seller" },
423
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_REVIEWS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_REVIEWS, label: "Reviews", variant: "outline", iconName: "Star", requiresAuth: true, requiredRole: "seller" },
424
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_PRODUCTS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_PRODUCTS, label: "My Products", variant: "outline", iconName: "Package", requiresAuth: true, requiredRole: "seller" },
425
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_STOREFRONT]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_STOREFRONT, label: "My Storefront", variant: "outline", iconName: "Store", requiresAuth: true, requiredRole: "seller" },
426
+ [DASHBOARD_QUICK_ACTION_ID.SELLER_ANALYTICS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ANALYTICS, label: "Analytics", variant: "outline", iconName: "BarChart", requiresAuth: true, requiredRole: "seller" },
380
427
  [DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS, label: "My Orders", variant: "outline", iconName: "Package", requiresAuth: true, requiredRole: "user" },
381
428
  [DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST, label: "Wishlist", variant: "outline", iconName: "Heart", requiresAuth: true, requiredRole: "user" },
382
429
  [DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE]: { id: DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE, label: "Edit Profile", variant: "outline", iconName: "User", requiresAuth: true, requiredRole: "user" },
383
430
  [DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS, label: "Add Address", variant: "outline", iconName: "MapPin", requiresAuth: true, requiredRole: "user" },
431
+ [DASHBOARD_QUICK_ACTION_ID.USER_RECENTLY_VIEWED]: { id: DASHBOARD_QUICK_ACTION_ID.USER_RECENTLY_VIEWED, label: "Recently Viewed", variant: "outline", iconName: "Clock", requiresAuth: true, requiredRole: "user" },
432
+ [DASHBOARD_QUICK_ACTION_ID.USER_MY_CATALOGUE]: { id: DASHBOARD_QUICK_ACTION_ID.USER_MY_CATALOGUE, label: "My Catalogue", variant: "outline", iconName: "Archive", requiresAuth: true, requiredRole: "user" },
433
+ [DASHBOARD_QUICK_ACTION_ID.USER_MY_COUPONS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_MY_COUPONS, label: "My Coupons", variant: "outline", iconName: "Ticket", requiresAuth: true, requiredRole: "user" },
384
434
  };
385
435
  // Quick action groups — ordered left-to-right in the top shortcut bar
386
436
  export const DASHBOARD_QUICK_ACTIONS = {
@@ -391,13 +441,35 @@ export const DASHBOARD_QUICK_ACTIONS = {
391
441
  DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_COUPON,
392
442
  DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_EVENT,
393
443
  DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG,
444
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_USERS,
445
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_STORES,
446
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_ORDERS,
447
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_PAYOUTS,
448
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_ANALYTICS,
449
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_CATEGORIES,
450
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_REVIEWS,
451
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_EVENTS,
452
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_FAQS,
453
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_CAROUSEL,
454
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_SECTIONS,
455
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_SUPPORT,
456
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_MODERATION,
457
+ DASHBOARD_QUICK_ACTION_ID.ADMIN_INTEGRATION_GUIDES,
394
458
  DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS,
395
459
  ],
396
460
  seller: [
397
461
  DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT,
398
- DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON,
462
+ DASHBOARD_QUICK_ACTION_ID.SELLER_PRODUCTS,
399
463
  DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS,
464
+ DASHBOARD_QUICK_ACTION_ID.SELLER_ANALYTICS,
465
+ DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON,
466
+ DASHBOARD_QUICK_ACTION_ID.SELLER_AUCTIONS,
400
467
  DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ,
468
+ DASHBOARD_QUICK_ACTION_ID.SELLER_SHIPPING,
469
+ DASHBOARD_QUICK_ACTION_ID.SELLER_MESSAGES,
470
+ DASHBOARD_QUICK_ACTION_ID.SELLER_WHATSAPP,
471
+ DASHBOARD_QUICK_ACTION_ID.SELLER_REVIEWS,
472
+ DASHBOARD_QUICK_ACTION_ID.SELLER_STOREFRONT,
401
473
  DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS,
402
474
  ],
403
475
  user: [
@@ -405,6 +477,9 @@ export const DASHBOARD_QUICK_ACTIONS = {
405
477
  DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST,
406
478
  DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE,
407
479
  DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS,
480
+ DASHBOARD_QUICK_ACTION_ID.USER_RECENTLY_VIEWED,
481
+ DASHBOARD_QUICK_ACTION_ID.USER_MY_CATALOGUE,
482
+ DASHBOARD_QUICK_ACTION_ID.USER_MY_COUPONS,
408
483
  ],
409
484
  };
410
485
  // Admin bulk actions per listing entity — used in BulkActionsBar on admin tables
@@ -451,6 +526,7 @@ export const ADMIN_BULK_ACTIONS = {
451
526
  // Seller bulk actions per listing entity
452
527
  export const SELLER_BULK_ACTIONS = {
453
528
  products: [ROW_ACTION_ID.PUBLISH, ROW_ACTION_ID.ARCHIVE, ROW_ACTION_ID.DELETE],
529
+ payouts: [ROW_ACTION_ID.EXPORT],
454
530
  coupons: [ROW_ACTION_ID.ARCHIVE, ROW_ACTION_ID.DELETE],
455
531
  bids: [ROW_ACTION_ID.CANCEL],
456
532
  bundles: [ROW_ACTION_ID.DELETE],