@mohasinac/appkit 4.2.0 → 4.3.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 (243) hide show
  1. package/dist/_internal/server/features/auth/actions.d.ts +0 -1
  2. package/dist/_internal/server/features/auth/actions.js +0 -1
  3. package/dist/_internal/server/features/bundles/data.d.ts +22 -4
  4. package/dist/_internal/server/features/bundles/data.js +41 -4
  5. package/dist/_internal/server/features/bundles/index.d.ts +1 -1
  6. package/dist/_internal/server/features/bundles/index.js +1 -1
  7. package/dist/_internal/server/features/checkout/actions.js +7 -78
  8. package/dist/_internal/server/features/checkout/prize-bundle-gates.d.ts +5 -16
  9. package/dist/_internal/server/features/checkout/prize-bundle-gates.js +5 -30
  10. package/dist/_internal/server/features/orders/adapters.js +1 -14
  11. package/dist/_internal/server/features/products/actions.js +8 -3
  12. package/dist/_internal/server/features/products/service.d.ts +15 -0
  13. package/dist/_internal/server/features/products/service.js +41 -0
  14. package/dist/_internal/server/functions/firestore.d.ts +3 -1
  15. package/dist/_internal/server/functions/firestore.js +17 -1
  16. package/dist/_internal/server/functions/scheduled.d.ts +2 -5
  17. package/dist/_internal/server/functions/scheduled.js +6 -30
  18. package/dist/_internal/server/jobs/core/bundleStockSync.js +25 -7
  19. package/dist/_internal/server/jobs/core/countersReconcile.js +7 -1
  20. package/dist/_internal/server/jobs/core/index.d.ts +4 -4
  21. package/dist/_internal/server/jobs/core/index.js +4 -4
  22. package/dist/_internal/server/jobs/core/onPrizeDrawPaymentConfirmed.d.ts +19 -0
  23. package/dist/_internal/server/jobs/core/onPrizeDrawPaymentConfirmed.js +30 -0
  24. package/dist/_internal/server/jobs/core/paymentWindowTimeout.d.ts +2 -2
  25. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +2 -2
  26. package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.d.ts +20 -0
  27. package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +113 -0
  28. package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.d.ts +14 -0
  29. package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +74 -0
  30. package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.d.ts +22 -0
  31. package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +68 -0
  32. package/dist/_internal/server/jobs/handlers/index.d.ts +3 -4
  33. package/dist/_internal/server/jobs/handlers/index.js +8 -6
  34. package/dist/_internal/server/jobs/handlers/onPrizeDrawPaymentConfirmed.d.ts +3 -0
  35. package/dist/_internal/server/jobs/handlers/onPrizeDrawPaymentConfirmed.js +11 -0
  36. package/dist/_internal/server/jobs/handlers/prizeDrawExpiryReveal.d.ts +2 -0
  37. package/dist/_internal/server/jobs/handlers/prizeDrawExpiryReveal.js +2 -0
  38. package/dist/_internal/server/jobs/handlers/prizeDrawSoldOutReveal.d.ts +3 -0
  39. package/dist/_internal/server/jobs/handlers/prizeDrawSoldOutReveal.js +4 -0
  40. package/dist/_internal/shared/actions/action-registry.js +40 -10
  41. package/dist/_internal/shared/checkout/rules/_defaults.js +1 -2
  42. package/dist/_internal/shared/checkout/rules/_limits.d.ts +3 -0
  43. package/dist/_internal/shared/checkout/rules/_limits.js +3 -0
  44. package/dist/_internal/shared/checkout/rules/_registry.d.ts +2 -1
  45. package/dist/_internal/shared/checkout/rules/_registry.js +2 -2
  46. package/dist/_internal/shared/checkout/rules/classified.rule.js +0 -1
  47. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  48. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  49. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +20 -1
  50. package/dist/_internal/shared/checkout/rules/types.d.ts +17 -7
  51. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +2 -0
  52. package/dist/_internal/shared/features/categories/bundle-copy.js +2 -0
  53. package/dist/_internal/shared/features/categories/bundle-pricing.d.ts +23 -0
  54. package/dist/_internal/shared/features/categories/bundle-pricing.js +25 -0
  55. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -1
  56. package/dist/constants/api-endpoints.d.ts +6 -9
  57. package/dist/constants/api-endpoints.js +5 -5
  58. package/dist/constants/field-names.d.ts +17 -1
  59. package/dist/constants/field-names.js +17 -1
  60. package/dist/features/account/hooks/useNotifications.js +5 -0
  61. package/dist/features/admin/actions/admin-actions.js +6 -0
  62. package/dist/features/admin/actions/notification-actions.js +1 -2
  63. package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
  64. package/dist/features/admin/components/AdminPrizeDrawsView.js +3 -3
  65. package/dist/features/admin/components/AdminSiteSettingsView.js +33 -6
  66. package/dist/features/admin/components/AdminTesterChecklistView.js +74 -22
  67. package/dist/features/admin/hooks/useAdminListing.d.ts +4 -0
  68. package/dist/features/admin/hooks/useAdminListing.js +4 -2
  69. package/dist/features/admin/schemas/firestore.d.ts +13 -5
  70. package/dist/features/admin/schemas/firestore.js +1 -2
  71. package/dist/features/auctions/actions/bid-actions.js +3 -1
  72. package/dist/features/auctions/components/AuctionBidsTable.d.ts +6 -1
  73. package/dist/features/auctions/components/AuctionBidsTable.js +8 -4
  74. package/dist/features/auctions/components/AuctionDetailPageView.js +10 -13
  75. package/dist/features/auctions/components/CollapsibleBidHistory.d.ts +23 -2
  76. package/dist/features/auctions/components/CollapsibleBidHistory.js +21 -3
  77. package/dist/features/auctions/components/LiveBidPrice.d.ts +19 -0
  78. package/dist/features/auctions/components/LiveBidPrice.js +17 -0
  79. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -1
  80. package/dist/features/auctions/components/PlaceBidFormClient.js +16 -1
  81. package/dist/features/auctions/hooks/useBids.d.ts +33 -0
  82. package/dist/features/auctions/hooks/useBids.js +32 -0
  83. package/dist/features/auctions/hooks/useLiveAuctionBid.d.ts +20 -0
  84. package/dist/features/auctions/hooks/useLiveAuctionBid.js +23 -0
  85. package/dist/features/auth/checkout-value-otp.d.ts +7 -10
  86. package/dist/features/auth/checkout-value-otp.js +14 -10
  87. package/dist/features/auth/server.d.ts +0 -1
  88. package/dist/features/auth/server.js +0 -1
  89. package/dist/features/blog/api/[slug]/route.d.ts +5 -0
  90. package/dist/features/blog/api/[slug]/route.js +12 -3
  91. package/dist/features/blog/components/BlogPostView.d.ts +2 -0
  92. package/dist/features/blog/components/BlogPostView.js +5 -4
  93. package/dist/features/blog/hooks/useBlog.d.ts +2 -0
  94. package/dist/features/blog/hooks/useBlog.js +2 -0
  95. package/dist/features/blog/repository/blog.repository.d.ts +7 -0
  96. package/dist/features/blog/repository/blog.repository.js +44 -0
  97. package/dist/features/blog/schemas/firestore.d.ts +3 -0
  98. package/dist/features/blog/schemas/firestore.js +1 -0
  99. package/dist/features/blog/types/index.d.ts +2 -0
  100. package/dist/features/cart/components/index.d.ts +0 -2
  101. package/dist/features/cart/components/index.js +0 -1
  102. package/dist/features/cart/hooks/useCartCount.js +22 -5
  103. package/dist/features/cart/hooks/useGuestCart.js +11 -1
  104. package/dist/features/cart/utils/guest-cart.d.ts +4 -0
  105. package/dist/features/cart/utils/guest-cart.js +10 -0
  106. package/dist/features/cart/utils/pending-ops.d.ts +17 -0
  107. package/dist/features/cart/utils/pending-ops.js +46 -5
  108. package/dist/features/categories/components/BrandDetailPageView.js +6 -2
  109. package/dist/features/categories/components/BundleDetailView.js +4 -2
  110. package/dist/features/categories/components/CategoryDetailPageView.js +10 -2
  111. package/dist/features/categories/schemas/firestore.d.ts +7 -0
  112. package/dist/features/checkout/actions/index.d.ts +0 -1
  113. package/dist/features/checkout/actions/index.js +0 -1
  114. package/dist/features/checkout/schemas/firestore.d.ts +2 -2
  115. package/dist/features/events/actions/event-actions.d.ts +2 -0
  116. package/dist/features/events/actions/event-actions.js +5 -0
  117. package/dist/features/events/components/EventCard.js +1 -2
  118. package/dist/features/events/components/RelatedEventsCarousel.d.ts +15 -0
  119. package/dist/features/events/components/RelatedEventsCarousel.js +13 -0
  120. package/dist/features/events/components/index.d.ts +2 -0
  121. package/dist/features/events/components/index.js +1 -0
  122. package/dist/features/events/repository/events.repository.d.ts +6 -0
  123. package/dist/features/events/repository/events.repository.js +21 -0
  124. package/dist/features/history/repository/user-history.repository.d.ts +1 -1
  125. package/dist/features/history/utils/guest-history.d.ts +1 -1
  126. package/dist/features/homepage/components/FeaturedBundlesSection.js +4 -2
  127. package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
  128. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  129. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  130. package/dist/features/layout/AppLayoutShell.js +1 -1
  131. package/dist/features/layout/NavbarLayout.js +1 -1
  132. package/dist/features/layout/TitleBarLayout.js +2 -2
  133. package/dist/features/media/MediaVideo.d.ts +7 -0
  134. package/dist/features/media/MediaVideo.js +36 -5
  135. package/dist/features/orders/components/OrdersList.js +1 -5
  136. package/dist/features/orders/schemas/firestore.d.ts +2 -8
  137. package/dist/features/orders/schemas/index.d.ts +3 -32
  138. package/dist/features/orders/schemas/index.js +1 -4
  139. package/dist/features/orders/types/index.d.ts +6 -9
  140. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
  141. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -1
  142. package/dist/features/products/actions/product-actions.js +13 -10
  143. package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
  144. package/dist/features/products/components/MarketplaceBundleCard.js +7 -4
  145. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  146. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  147. package/dist/features/products/components/PrizeDrawWinnerMappingView.d.ts +14 -0
  148. package/dist/features/products/components/PrizeDrawWinnerMappingView.js +37 -0
  149. package/dist/features/products/components/PrizeRevealModal.d.ts +10 -23
  150. package/dist/features/products/components/PrizeRevealModal.js +18 -147
  151. package/dist/features/products/components/ProductDetailPageView.js +72 -30
  152. package/dist/features/products/components/ProductForm.js +7 -14
  153. package/dist/features/products/components/ProductGalleryClient.d.ts +10 -1
  154. package/dist/features/products/components/ProductGalleryClient.js +29 -10
  155. package/dist/features/products/components/ProductsIndexListing.js +2 -1
  156. package/dist/features/products/components/RelatedProductsCarousel.js +2 -2
  157. package/dist/features/products/components/ShowGroupSection.js +2 -2
  158. package/dist/features/products/components/SublistingCarouselSection.js +1 -1
  159. package/dist/features/products/components/index.d.ts +4 -2
  160. package/dist/features/products/components/index.js +1 -0
  161. package/dist/features/products/constants/action-defs.d.ts +0 -1
  162. package/dist/features/products/constants/action-defs.js +0 -2
  163. package/dist/features/products/repository/products.repository.d.ts +6 -0
  164. package/dist/features/products/repository/products.repository.js +20 -1
  165. package/dist/features/products/schemas/firestore.d.ts +26 -2
  166. package/dist/features/products/schemas/index.d.ts +11 -3
  167. package/dist/features/products/schemas/index.js +10 -2
  168. package/dist/features/products/types/index.d.ts +2 -1
  169. package/dist/features/reviews/actions/review-actions.js +1 -0
  170. package/dist/features/reviews/components/ReviewDetailPageView.js +8 -1
  171. package/dist/features/reviews/components/ReviewDetailShell.js +2 -1
  172. package/dist/features/reviews/components/ReviewsList.js +2 -1
  173. package/dist/features/reviews/schemas/firestore.d.ts +3 -0
  174. package/dist/features/reviews/schemas/index.d.ts +6 -0
  175. package/dist/features/reviews/schemas/index.js +2 -0
  176. package/dist/features/reviews/types/index.d.ts +3 -0
  177. package/dist/features/scams/actions/scam-actions.d.ts +3 -0
  178. package/dist/features/scams/actions/scam-actions.js +3 -2
  179. package/dist/features/scams/components/ScamProfileView.d.ts +2 -1
  180. package/dist/features/scams/components/ScamProfileView.js +2 -2
  181. package/dist/features/scams/repository/scammer.repository.d.ts +6 -0
  182. package/dist/features/scams/repository/scammer.repository.js +24 -0
  183. package/dist/features/seller/actions/seller-actions.js +8 -0
  184. package/dist/features/seller/components/SellerPrizeDrawsView.js +4 -0
  185. package/dist/features/stores/components/StoreDetailLayoutView.js +6 -6
  186. package/dist/features/stores/components/StoreNavTabs.d.ts +10 -1
  187. package/dist/features/stores/components/StoreNavTabs.js +21 -9
  188. package/dist/features/tester/actions/index.d.ts +1 -0
  189. package/dist/features/tester/actions/index.js +1 -0
  190. package/dist/features/tester/actions/leaderboard-actions.d.ts +3 -0
  191. package/dist/features/tester/actions/leaderboard-actions.js +5 -0
  192. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +26 -4
  193. package/dist/features/tester/components/AdminTesterFeedbackListView.js +13 -0
  194. package/dist/features/tester/components/BugHunterLeaderboardView.d.ts +23 -0
  195. package/dist/features/tester/components/BugHunterLeaderboardView.js +18 -0
  196. package/dist/features/tester/components/index.d.ts +2 -0
  197. package/dist/features/tester/components/index.js +1 -0
  198. package/dist/features/tester/repository/tester-checklist-item.repository.d.ts +12 -1
  199. package/dist/features/tester/repository/tester-checklist-item.repository.js +80 -0
  200. package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +4 -0
  201. package/dist/features/tester/repository/tester-checklist-response.repository.js +4 -0
  202. package/dist/features/tester/schemas/firestore.d.ts +22 -1
  203. package/dist/features/tester/schemas/firestore.js +8 -0
  204. package/dist/features/tester/seed-data/categories-tester-seed-data.js +42 -7
  205. package/dist/features/tester/seed-data/events-tester-seed-data.js +23 -0
  206. package/dist/features/tester/seed-data/orders-tester-seed-data.js +69 -31
  207. package/dist/features/tester/seed-data/products-tester-seed-data.js +152 -8
  208. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +249 -14
  209. package/dist/features/wishlist/hooks/useGuestWishlist.js +11 -1
  210. package/dist/features/wishlist/hooks/useWishlistCount.js +16 -2
  211. package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -0
  212. package/dist/features/wishlist/utils/guest-wishlist.js +11 -0
  213. package/dist/index.d.ts +19 -22
  214. package/dist/index.js +25 -58
  215. package/dist/jobs.d.ts +1 -1
  216. package/dist/jobs.js +2 -2
  217. package/dist/next/routing/route-map.d.ts +2 -0
  218. package/dist/next/routing/route-map.js +1 -0
  219. package/dist/schemas/registry.d.ts +6 -26
  220. package/dist/seed/bids-seed-data.js +14 -2
  221. package/dist/seed/blog-posts-seed-data.js +2 -1
  222. package/dist/seed/categories-seed-data.js +11 -2
  223. package/dist/seed/events-seed-data.js +11 -11
  224. package/dist/seed/faq-seed-data.js +5 -1
  225. package/dist/seed/products-auctions-seed-data.js +2 -2
  226. package/dist/seed/products-preorders-seed-data.d.ts +2 -1
  227. package/dist/seed/products-prize-draws-seed-data.js +56 -10
  228. package/dist/seed/products-standard-seed-data.js +82 -3
  229. package/dist/seed/scammers-seed-data.js +75 -2
  230. package/dist/seed/site-settings-seed-data.js +5 -2
  231. package/dist/server-entry.d.ts +0 -1
  232. package/dist/server-entry.js +0 -1
  233. package/dist/server.d.ts +4 -20
  234. package/dist/server.js +10 -57
  235. package/dist/styles.css +1 -1
  236. package/dist/tailwind-utilities.css +1 -1
  237. package/dist/ui/components/BaseListingCard.js +1 -1
  238. package/dist/ui/components/ImageLightbox.d.ts +9 -0
  239. package/dist/ui/components/ImageLightbox.js +6 -3
  240. package/dist/ui/components/ListingToolbar.d.ts +18 -1
  241. package/dist/ui/components/ListingToolbar.js +5 -2
  242. package/dist/ui/components/StickyToolbar.js +13 -8
  243. package/package.json +1 -1
@@ -28,6 +28,7 @@ export const testerChecklistItemQueryHelpers = {
28
28
  byGroup: (groupKey) => ["groupKey", "==", groupKey],
29
29
  byPage: (pageKey) => ["pageKey", "==", pageKey],
30
30
  active: () => ["isActive", "==", true],
31
+ confirmedBugs: () => ["bugConfirmed", "==", true],
31
32
  };
32
33
  export function slugifyChecklistLabel(label) {
33
34
  return label
@@ -81,6 +82,13 @@ export const TESTER_CHECKLIST_ITEM_FIELDS = {
81
82
  IS_ACTIVE: "isActive",
82
83
  SEARCH_TOKENS: "searchTokens",
83
84
  ADMIN_ONLY: "adminOnly",
85
+ BUG_CONFIRMED: "bugConfirmed",
86
+ BUG_HUNTER_ID: "bugHunterId",
87
+ BUG_HUNTER_NAME: "bugHunterName",
88
+ BUG_CONFIRMED_AT: "bugConfirmedAt",
89
+ VERSION: "version",
90
+ PREVIOUS_VERSION_ID: "previousVersionId",
91
+ SUPERSEDED_BY_ITEM_ID: "supersededByItemId",
84
92
  CREATED_AT: "createdAt",
85
93
  UPDATED_AT: "updatedAt",
86
94
  };
@@ -1,9 +1,11 @@
1
1
  /*
2
- * WHY: Shared tester sandbox — a small self-contained category tree (root + 2 leaves),
3
- * 1 brand row, and 1 bundle row so testers can exercise browsing/filtering/bundle
4
- * flows without touching real catalog data. Auto-expires after 7 days.
5
- * WHAT: Exports categoriesTesterSeedData — 3 plain categories + 1 categoryType:"brand" +
6
- * 1 categoryType:"bundle" (bundleProductIds references products-tester-seed-data.ts).
2
+ * WHY: Shared tester sandbox — a small self-contained category tree (root + 3 leaves,
3
+ * one leaf deliberately isActive:false), 1 brand row, and 1 bundle row so testers
4
+ * can exercise browsing/filtering/bundle flows without touching real catalog data.
5
+ * Auto-expires after 7 days.
6
+ * WHAT: Exports categoriesTesterSeedData — 4 plain categories + 1 categoryType:"brand" +
7
+ * 1 categoryType:"bundle" (bundleProductIds + bundleOriginalTotal reference
8
+ * products-tester-seed-data.ts).
7
9
  *
8
10
  * EXPORTS:
9
11
  * categoriesTesterSeedData — Array of Partial<CategoryDocument> for the seed runner
@@ -37,13 +39,13 @@ export const categoriesTesterSeedData = [
37
39
  description: "Disposable test category tree for the tester QA program.",
38
40
  rootId: "category-tester-sandbox",
39
41
  parentIds: [],
40
- childrenIds: ["category-tester-gadgets", "category-tester-collectibles"],
42
+ childrenIds: ["category-tester-gadgets", "category-tester-collectibles", "category-tester-inactive"],
41
43
  tier: 0,
42
44
  path: "tester-sandbox",
43
45
  order: 999,
44
46
  isLeaf: false,
45
47
  position: 0,
46
- subtreeSize: 2,
48
+ subtreeSize: 3,
47
49
  metrics: emptyMetrics,
48
50
  isFeatured: false,
49
51
  isBrand: false,
@@ -110,6 +112,36 @@ export const categoriesTesterSeedData = [
110
112
  createdAt: new Date(),
111
113
  updatedAt: new Date(),
112
114
  },
115
+ {
116
+ // Deliberately isActive:false — the entire real seed dataset (17 categories
117
+ // before this) has isActive:true on every single row, so the admin Categories
118
+ // dashboard's "isActive" toggle (backed by the categories(isActive, name ASC)
119
+ // composite index) had nothing to show when toggled to the inactive branch.
120
+ id: "category-tester-inactive",
121
+ slug: "category-tester-inactive",
122
+ name: "Test Inactive Category",
123
+ description: "Disposable test category deliberately seeded as inactive, for verifying the admin Categories isActive toggle. Auto-expires in 7 days.",
124
+ rootId: "category-tester-sandbox",
125
+ parentIds: ["category-tester-sandbox"],
126
+ childrenIds: [],
127
+ tier: 1,
128
+ path: "tester-sandbox/inactive",
129
+ order: 3,
130
+ isLeaf: true,
131
+ position: 2,
132
+ subtreeSize: 0,
133
+ metrics: emptyMetrics,
134
+ isFeatured: false,
135
+ isBrand: false,
136
+ isActive: false,
137
+ isSearchable: false,
138
+ showOnHomepage: false,
139
+ createdBy: "user-admin-letitrip",
140
+ isTestData: true,
141
+ testDataExpiresAt: testDataExpiresAt(),
142
+ createdAt: new Date(),
143
+ updatedAt: new Date(),
144
+ },
113
145
  // ── BRAND ────────────────────────────────────────────────────────────────
114
146
  {
115
147
  id: "brand-tester-sandbox",
@@ -153,6 +185,9 @@ export const categoriesTesterSeedData = [
153
185
  type: "static",
154
186
  productIds: ["product-tester-standard-1", "product-tester-standard-2"],
155
187
  },
188
+ bundleProductIds: ["product-tester-standard-1", "product-tester-standard-2"],
189
+ bundleOriginalTotal: 348, // 199 + 149
190
+ bundleStockStatus: "in_stock",
156
191
  rootId: "bundle-tester-sandbox",
157
192
  parentIds: [],
158
193
  childrenIds: [],
@@ -95,4 +95,27 @@ export const eventsTesterSeedData = [
95
95
  createdAt: new Date(),
96
96
  updatedAt: new Date(),
97
97
  },
98
+ {
99
+ id: "event-tester-sandbox-offer",
100
+ slug: "tester-sandbox-offer",
101
+ type: EVENT_FIELDS.TYPE_VALUES.OFFER,
102
+ title: "Tester Sandbox — Offer Coupon",
103
+ description: "Disposable test event for the tester QA program. Verify the Overview tab shows the coupon code and the Copy code button copies it to the clipboard.",
104
+ status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
105
+ startsAt: new Date(),
106
+ endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
107
+ coverImage: { type: "image", url: seedExtMedia("https://picsum.photos/seed/event-cover-tester-sandbox-offer-20260101/1200/600"), alt: TEST_EVENT_COVER_ALT },
108
+ tags: ["test"],
109
+ offerConfig: {
110
+ couponId: "coupon-rehan10",
111
+ displayCode: "REHAN10",
112
+ bannerText: "Test offer — not a real discount.",
113
+ },
114
+ stats: { totalEntries: 0, approvedEntries: 0, flaggedEntries: 0 },
115
+ createdBy: "user-admin-letitrip",
116
+ isTestData: true,
117
+ testDataExpiresAt: testDataExpiresAt(),
118
+ createdAt: new Date(),
119
+ updatedAt: new Date(),
120
+ },
98
121
  ];
@@ -5,7 +5,11 @@
5
5
  * without manually driving each one through the full checkout/shipping/return
6
6
  * flow first. Buyer is the dedicated user-tester-qa persona. Auto-expires in 7
7
7
  * days via testerSandboxCleanup (orders aren't cascade-deleted — see note below).
8
- * WHAT: Exports ordersTesterSeedData 13 Partial<OrderDocument> for the seed runner.
8
+ * Also includes one 5-item order specifically to exercise the "My Orders" /
9
+ * dashboard Recent Orders item-summary UI (thumbnails/title/qty for the first 3
10
+ * items + a "+N more" badge beyond that) — the other fixtures here are all
11
+ * single- or 2-item orders, which never trigger the "+N more" badge at all.
12
+ * WHAT: Exports ordersTesterSeedData — 14 Partial<OrderDocument> for the seed runner.
9
13
  *
10
14
  * NOTE: OrderDocument does not currently carry isTestData/testDataExpiresAt (unlike
11
15
  * categories/stores/products/blogPosts/events) — testerSandboxCleanup does not
@@ -14,7 +18,7 @@
14
18
  * orders is a follow-up, not blocking.
15
19
  *
16
20
  * EXPORTS:
17
- * ordersTesterSeedData — Array of 13 Partial<OrderDocument> for the seed runner
21
+ * ordersTesterSeedData — Array of 14 Partial<OrderDocument> for the seed runner
18
22
  *
19
23
  * @tag domain:orders,tester
20
24
  * @tag layer:seed
@@ -139,11 +143,16 @@ export const ordersTesterSeedData = [
139
143
  createdAt: daysAgo(1),
140
144
  updatedAt: NOW,
141
145
  },
142
- // ── Bundle purchase — group-tester-sandbox-bundle expands into its two children ──
146
+ // ── Bundle purchase — a real checkout produces ONE order item for the whole
147
+ // bundle (see addBundleToCartAction / checkout/actions.ts bundle-expansion),
148
+ // not one item per member product. Previously mis-modeled against
149
+ // "group-tester-sandbox-bundle" (a real standalone product that separately
150
+ // demonstrates the Tier-GP product-group "Set" feature, not a bundle at
151
+ // all) — the actual bundle is the categories row "bundle-tester-sandbox".
143
152
  {
144
153
  id: "order-tester-sandbox-bundle",
145
- productId: "group-tester-sandbox-bundle",
146
- productTitle: "Test Bundle — Standard #1 + Standard #2",
154
+ productId: "bundle-tester-sandbox",
155
+ productTitle: "Test Bundle",
147
156
  userId: BUYER_ID,
148
157
  userName: BUYER_NAME,
149
158
  userEmail: BUYER_EMAIL,
@@ -151,32 +160,22 @@ export const ordersTesterSeedData = [
151
160
  storeName: STORE_NAME,
152
161
  items: [
153
162
  {
154
- productId: "product-tester-standard-1",
155
- productTitle: "Test Gadget — Standard Listing #1",
163
+ productId: "bundle-tester-sandbox",
164
+ productTitle: "Test Bundle",
156
165
  listingType: "standard",
157
166
  quantity: 1,
158
167
  unitPrice: 199,
159
168
  totalPrice: 199,
160
- bundleCategorySlug: "group-tester-sandbox-bundle",
161
- bundleProductIds: ["product-tester-standard-1", "product-tester-standard-2"],
162
- },
163
- {
164
- productId: "product-tester-standard-2",
165
- productTitle: "Test Collectible — Standard Listing #2",
166
- listingType: "standard",
167
- quantity: 1,
168
- unitPrice: 149,
169
- totalPrice: 149,
170
- bundleCategorySlug: "group-tester-sandbox-bundle",
169
+ bundleCategorySlug: "bundle-tester-sandbox",
171
170
  bundleProductIds: ["product-tester-standard-1", "product-tester-standard-2"],
172
171
  },
173
172
  ],
174
173
  orderType: "standard",
175
- bundleId: "group-tester-sandbox-bundle",
174
+ bundleId: "bundle-tester-sandbox",
176
175
  isNonRefundable: true,
177
- quantity: 2,
178
- unitPrice: 164,
179
- totalPrice: 329,
176
+ quantity: 1,
177
+ unitPrice: 199,
178
+ totalPrice: 199,
180
179
  currency: "INR",
181
180
  status: "processing",
182
181
  paymentStatus: "paid",
@@ -206,13 +205,12 @@ export const ordersTesterSeedData = [
206
205
  unitPrice: 50,
207
206
  totalPrice: 50,
208
207
  prizeRevealStatus: "revealed",
209
- revealedItemNumber: 1,
210
208
  },
211
209
  ],
212
210
  orderType: "prize-draw",
213
211
  prizeDrawProductId: PRIZEDRAW_PRODUCT_ID,
212
+ prizeRevealMode: "scheduled",
214
213
  prizeWon: { itemNumber: 1, title: "Test Prize — Grand", images: [], wonAt: daysAgo(1) },
215
- prizeRevealDeadline: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
216
214
  isNonRefundable: true,
217
215
  quantity: 1,
218
216
  unitPrice: 50,
@@ -225,7 +223,11 @@ export const ordersTesterSeedData = [
225
223
  createdAt: daysAgo(1),
226
224
  updatedAt: daysAgo(1),
227
225
  },
228
- // ── Prize draw — non-winning entry, auto-refunded ────────────────────────────
226
+ // ── Prize draw — a second entry on the same closed draw, revealed to a
227
+ // different item. Every paid entry on a prize draw is eventually
228
+ // assigned some item (prizeMaxEntries === item count) — there's no
229
+ // "losing" outcome under the automatic-reveal model, unlike a lottery
230
+ // with fewer prizes than tickets. ─────────────────────────────────────
229
231
  {
230
232
  id: "order-tester-sandbox-prizedraw-lose",
231
233
  productId: PRIZEDRAW_PRODUCT_ID,
@@ -243,23 +245,59 @@ export const ordersTesterSeedData = [
243
245
  quantity: 1,
244
246
  unitPrice: 50,
245
247
  totalPrice: 50,
246
- prizeRevealStatus: "closed",
248
+ prizeRevealStatus: "revealed",
247
249
  },
248
250
  ],
249
251
  orderType: "prize-draw",
250
252
  prizeDrawProductId: PRIZEDRAW_PRODUCT_ID,
253
+ prizeRevealMode: "scheduled",
254
+ prizeWon: { itemNumber: 2, title: "Test Prize — Runner-up", images: [], wonAt: daysAgo(1) },
255
+ isNonRefundable: true,
251
256
  quantity: 1,
252
257
  unitPrice: 50,
253
258
  totalPrice: 50,
254
259
  currency: "INR",
255
- status: "refunded",
256
- paymentStatus: "refunded",
260
+ status: "delivered",
261
+ paymentStatus: "paid",
257
262
  paymentMethod: "upi_manual",
258
- refundAmount: 50,
259
- refundStatus: "completed",
260
- refundNote: "Disposable test — non-winning prize-draw entry auto-refunded after reveal.",
261
263
  orderDate: daysAgo(1),
262
264
  createdAt: daysAgo(1),
263
265
  updatedAt: NOW,
264
266
  },
267
+ // ── Multi-item order — 5 line items so the "My Orders" list / dashboard Recent
268
+ // Orders widget shows real thumbnails+title+qty for the first 3 and a genuine
269
+ // "+2 more" badge for the rest (every other fixture above tops out at 2 items).
270
+ {
271
+ id: "order-tester-sandbox-multi-item",
272
+ productId: STANDARD_PRODUCT_ID,
273
+ productTitle: STANDARD_PRODUCT_TITLE,
274
+ userId: BUYER_ID,
275
+ userName: BUYER_NAME,
276
+ userEmail: BUYER_EMAIL,
277
+ storeId: STORE_ID,
278
+ storeName: STORE_NAME,
279
+ items: [
280
+ { productId: "product-tester-standard-1", productTitle: "Test Gadget — Standard Listing #1", listingType: "standard", quantity: 1, unitPrice: 199, totalPrice: 199 },
281
+ { productId: "product-tester-standard-2", productTitle: "Test Collectible — Standard Listing #2", listingType: "standard", quantity: 1, unitPrice: 149, totalPrice: 149 },
282
+ { productId: "product-tester-standard-accessory-case", productTitle: "Test Accessory — Carry Case", listingType: "standard", quantity: 1, unitPrice: 99, totalPrice: 99 },
283
+ { productId: "product-tester-standard-accessory-stand", productTitle: "Test Accessory — Display Stand", listingType: "standard", quantity: 2, unitPrice: 49, totalPrice: 98 },
284
+ { productId: "product-tester-standard-accessory-stickers", productTitle: "Test Accessory — Sticker Set", listingType: "standard", quantity: 3, unitPrice: 19, totalPrice: 57 },
285
+ ],
286
+ orderType: "standard",
287
+ quantity: 8,
288
+ unitPrice: 199,
289
+ totalPrice: 602,
290
+ currency: "INR",
291
+ status: "delivered",
292
+ paymentStatus: "paid",
293
+ paymentMethod: "upi_manual",
294
+ shippingAddress: "addr-tester-qa-home",
295
+ trackingNumber: "TEST-TRACK-MULTI-001",
296
+ shippingCarrier: "Test Carrier",
297
+ shippingDate: daysAgo(2),
298
+ deliveryDate: daysAgo(1),
299
+ orderDate: daysAgo(3),
300
+ createdAt: daysAgo(3),
301
+ updatedAt: daysAgo(1),
302
+ },
265
303
  ];
@@ -1,9 +1,13 @@
1
1
  /*
2
- * WHY: Shared tester sandbox — a handful of disposable test products spanning standard,
3
- * auction, and pre-order listing types, all owned by store-tester-sandbox, so testers
4
- * can exercise buying/bidding/pre-ordering against real code paths. Auto-expires after
5
- * 7 days (testerSandboxCleanup cascades into any bids on the auction).
6
- * WHAT: Exports productsTesterSeedData 2 standard + 1 auction + 1 pre-order product.
2
+ * WHY: Shared tester sandbox — a handful of disposable test products spanning every listing
3
+ * type (standard, auction, pre-order, prize-draw, classified, digital-code, live, art,
4
+ * stickers), all owned by store-tester-sandbox, so testers can exercise buying/bidding/
5
+ * pre-ordering against real code paths including navigating every entry of the store
6
+ * detail page's listing-type dropdown (see StoreNavTabs). Auto-expires after 7 days
7
+ * (testerSandboxCleanup cascades into any bids on the auction).
8
+ * WHAT: Exports productsTesterSeedData — 2 standard + 2 auction + 1 pre-order + 1 prize-draw +
9
+ * 1 classified + 1 digital-code + 1 live + 1 art + 1 stickers product + 1 product-group
10
+ * ("Set") parent (product-tester-standard-1/2 are its children, linked via groupId).
7
11
  *
8
12
  * EXPORTS:
9
13
  * productsTesterSeedData — Array of Partial<ProductDocument> for the seed runner
@@ -61,6 +65,13 @@ export const productsTesterSeedData = [
61
65
  customSections: [],
62
66
  isPromoted: false,
63
67
  isOnSale: false,
68
+ // Child of the "group-tester-sandbox-bundle" product-group ("Set") parent
69
+ // below — findByGroupId() queries products by this field directly, so
70
+ // without it the parent's groupChildSlugs[] mirror is never actually
71
+ // resolvable and ShowGroupSection renders nothing (members.length <= 1).
72
+ groupId: "group-tester-sandbox-bundle",
73
+ groupParentSlug: "group-tester-sandbox-bundle",
74
+ groupTitle: "Tester Sandbox Bundle",
64
75
  createdAt: new Date(),
65
76
  updatedAt: new Date(),
66
77
  }),
@@ -87,6 +98,35 @@ export const productsTesterSeedData = [
87
98
  customSections: [],
88
99
  isPromoted: false,
89
100
  isOnSale: false,
101
+ groupId: "group-tester-sandbox-bundle",
102
+ groupParentSlug: "group-tester-sandbox-bundle",
103
+ groupTitle: "Tester Sandbox Bundle",
104
+ createdAt: new Date(),
105
+ updatedAt: new Date(),
106
+ }),
107
+ withTokens({
108
+ id: "product-tester-standard-sold",
109
+ slug: "product-tester-standard-sold",
110
+ title: "Test Collectible — Sold Out (Hidden by Default)",
111
+ description: "Disposable test product deliberately seeded as sold out — exists to verify the public/admin/seller \"Show sold\" toggle actually hides it by default and reveals it when toggled on. Auto-expires in 7 days.",
112
+ categorySlugs: COLLECTIBLES_CATEGORY_SLUGS,
113
+ categoryNames: COLLECTIBLES_CATEGORY_NAMES,
114
+ brandSlug: "brand-tester-sandbox",
115
+ brand: "TestBrand",
116
+ price: 179,
117
+ currency: "INR",
118
+ stockQuantity: 0,
119
+ availableQuantity: 0,
120
+ isSold: true,
121
+ mainImage: seedExtMedia("https://picsum.photos/seed/product-image-tester-standard-sold-20260101/900/900"),
122
+ images: [seedExtMedia("https://picsum.photos/seed/product-image-tester-standard-sold-20260101/900/900")],
123
+ status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
124
+ condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
125
+ listingType: "standard",
126
+ customFields: [],
127
+ customSections: [],
128
+ isPromoted: false,
129
+ isOnSale: false,
90
130
  createdAt: new Date(),
91
131
  updatedAt: new Date(),
92
132
  }),
@@ -170,6 +210,13 @@ export const productsTesterSeedData = [
170
210
  images: [seedExtMedia("https://picsum.photos/seed/preorder-image-tester-sandbox-1-20260101/900/900")],
171
211
  mainImage: seedExtMedia("https://picsum.photos/seed/preorder-image-tester-sandbox-1-20260101/900/900"),
172
212
  isSold: false,
213
+ // stockQuantity must be set (not just availableQuantity) — the public
214
+ // listing route's default "hide sold" filter is a Firestore inequality
215
+ // on stockQuantity, and Firestore excludes documents missing that field
216
+ // entirely from an inequality query, not just ones where it's 0. Without
217
+ // this the pre-order would be permanently invisible on the default
218
+ // /pre-orders listing (2026-08-19 index-sweep session).
219
+ stockQuantity: 5,
173
220
  availableQuantity: 5,
174
221
  customFields: [],
175
222
  customSections: [],
@@ -208,13 +255,14 @@ export const productsTesterSeedData = [
208
255
  isPromoted: false,
209
256
  isOnSale: false,
210
257
  prizeDrawMode: "reveal",
258
+ prizeRevealMode: "instant",
211
259
  pricePerEntry: 50,
212
260
  prizeMaxEntries: 3,
213
261
  prizeCurrentEntries: 0,
262
+ prizeDrawDurationDays: 7,
214
263
  prizeRevealWindowStart: new Date(),
215
264
  prizeRevealWindowEnd: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
216
265
  prizeRevealStatus: "open",
217
- prizeRevealDeadlineDays: 7,
218
266
  prizeDrawItems: [
219
267
  { itemNumber: 1, title: "Test Prize — Grand", description: "Disposable test grand prize.", images: [seedExtMedia("https://picsum.photos/seed/prizedraw-item-1-20260101/600/600")], condition: "new", estimatedValue: 500, isWon: false },
220
268
  { itemNumber: 2, title: "Test Prize — Runner-up", description: "Disposable test runner-up prize.", images: [seedExtMedia("https://picsum.photos/seed/prizedraw-item-2-20260101/600/600")], condition: "new", estimatedValue: 150, isWon: false },
@@ -223,6 +271,46 @@ export const productsTesterSeedData = [
223
271
  createdAt: new Date(),
224
272
  updatedAt: new Date(),
225
273
  }),
274
+ withTokens({
275
+ id: "prizedraw-tester-sandbox-closed",
276
+ slug: "prizedraw-tester-sandbox-closed",
277
+ title: "Test Prize Draw — Already Closed",
278
+ description: "Disposable test prize-draw, window already closed — exists to verify the admin/seller \"Show closed\" toggle actually hides it by default and reveals it when toggled on. Auto-expires in 7 days.",
279
+ categorySlugs: COLLECTIBLES_CATEGORY_SLUGS,
280
+ categoryNames: COLLECTIBLES_CATEGORY_NAMES,
281
+ brandSlug: "brand-tester-sandbox",
282
+ brand: "TestBrand",
283
+ price: 50,
284
+ currency: "INR",
285
+ condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
286
+ status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
287
+ listingType: "prize-draw",
288
+ images: [seedExtMedia("https://picsum.photos/seed/prizedraw-image-tester-sandbox-closed-20260101/900/900")],
289
+ mainImage: seedExtMedia("https://picsum.photos/seed/prizedraw-image-tester-sandbox-closed-20260101/900/900"),
290
+ isSold: true,
291
+ stockQuantity: 0,
292
+ availableQuantity: 0,
293
+ customFields: [],
294
+ customSections: [],
295
+ isPromoted: false,
296
+ isOnSale: false,
297
+ prizeDrawMode: "reveal",
298
+ prizeRevealMode: "scheduled",
299
+ pricePerEntry: 50,
300
+ prizeMaxEntries: 3,
301
+ prizeCurrentEntries: 3,
302
+ prizeDrawDurationDays: 13,
303
+ prizeRevealWindowStart: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000),
304
+ prizeRevealWindowEnd: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000),
305
+ prizeRevealStatus: "closed",
306
+ prizeDrawItems: [
307
+ { itemNumber: 1, title: "Test Prize — Grand", description: "Disposable test grand prize.", images: [seedExtMedia("https://picsum.photos/seed/prizedraw-item-closed-1-20260101/600/600")], condition: "new", estimatedValue: 500, isWon: true },
308
+ { itemNumber: 2, title: "Test Prize — Runner-up", description: "Disposable test runner-up prize.", images: [seedExtMedia("https://picsum.photos/seed/prizedraw-item-closed-2-20260101/600/600")], condition: "new", estimatedValue: 150, isWon: true },
309
+ { itemNumber: 3, title: "Test Prize — Consolation", description: "Disposable test consolation prize.", images: [seedExtMedia("https://picsum.photos/seed/prizedraw-item-closed-3-20260101/600/600")], condition: "new", estimatedValue: 20, isWon: true },
310
+ ],
311
+ createdAt: new Date(),
312
+ updatedAt: new Date(),
313
+ }),
226
314
  withTokens({
227
315
  id: "classified-tester-sandbox-1",
228
316
  slug: "classified-tester-sandbox-1",
@@ -323,11 +411,67 @@ export const productsTesterSeedData = [
323
411
  createdAt: new Date(),
324
412
  updatedAt: new Date(),
325
413
  }),
414
+ withTokens({
415
+ id: "art-tester-sandbox-1",
416
+ slug: "art-tester-sandbox-1",
417
+ title: "Test Art Print — Frame Me!",
418
+ description: "Disposable test art listing for the tester QA program. Auto-expires in 7 days.",
419
+ categorySlugs: COLLECTIBLES_CATEGORY_SLUGS,
420
+ categoryNames: COLLECTIBLES_CATEGORY_NAMES,
421
+ brandSlug: "brand-tester-sandbox",
422
+ brand: "TestBrand",
423
+ price: 349,
424
+ currency: "INR",
425
+ stockQuantity: 5,
426
+ availableQuantity: 5,
427
+ isSold: false,
428
+ mainImage: seedExtMedia("https://picsum.photos/seed/art-image-tester-sandbox-1-20260101/900/900"),
429
+ images: [seedExtMedia("https://picsum.photos/seed/art-image-tester-sandbox-1-20260101/900/900")],
430
+ status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
431
+ condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
432
+ listingType: "art",
433
+ customFields: [],
434
+ customSections: [],
435
+ isPromoted: false,
436
+ isOnSale: false,
437
+ createdAt: new Date(),
438
+ updatedAt: new Date(),
439
+ }),
440
+ withTokens({
441
+ id: "stickers-tester-sandbox-1",
442
+ slug: "stickers-tester-sandbox-1",
443
+ title: "Test Sticker Pack — Peel Me!",
444
+ description: "Disposable test stickers listing for the tester QA program. Auto-expires in 7 days.",
445
+ categorySlugs: GADGETS_CATEGORY_SLUGS,
446
+ categoryNames: GADGETS_CATEGORY_NAMES,
447
+ brandSlug: "brand-tester-sandbox",
448
+ brand: "TestBrand",
449
+ price: 79,
450
+ currency: "INR",
451
+ stockQuantity: 25,
452
+ availableQuantity: 25,
453
+ isSold: false,
454
+ mainImage: seedExtMedia("https://picsum.photos/seed/stickers-image-tester-sandbox-1-20260101/900/900"),
455
+ images: [seedExtMedia("https://picsum.photos/seed/stickers-image-tester-sandbox-1-20260101/900/900")],
456
+ status: PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED,
457
+ condition: PRODUCT_FIELDS.CONDITION_VALUES.NEW,
458
+ listingType: "stickers",
459
+ customFields: [],
460
+ customSections: [],
461
+ isPromoted: false,
462
+ isOnSale: false,
463
+ createdAt: new Date(),
464
+ updatedAt: new Date(),
465
+ }),
326
466
  withTokens({
327
467
  id: "group-tester-sandbox-bundle",
328
468
  slug: "group-tester-sandbox-bundle",
329
- title: "Test BundleStandard #1 + Standard #2",
330
- description: "Disposable test bundle bundling the two tester-sandbox standard products. Auto-expires in 7 days.",
469
+ // Product-group ("Set") parentTier GP, unrelated to the Bundles
470
+ // feature (categoryType:"bundle") despite the legacy "bundle" id/slug.
471
+ // Kept stable rather than renamed since nothing outside this file's
472
+ // internal group wiring depends on the "bundle" name.
473
+ title: "Test Product Set — Standard #1 + Standard #2",
474
+ description: "Disposable test product-group parent linking the two tester-sandbox standard products as a \"Set\". Auto-expires in 7 days.",
331
475
  categorySlugs: GADGETS_CATEGORY_SLUGS,
332
476
  categoryNames: GADGETS_CATEGORY_NAMES,
333
477
  brandSlug: "brand-tester-sandbox",