@mohasinac/appkit 4.1.0 → 4.1.3

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 (205) 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/maintenance/cloud-logs-data.d.ts +50 -0
  9. package/dist/_internal/server/features/maintenance/cloud-logs-data.js +152 -0
  10. package/dist/_internal/server/jobs/core/onOrderCreate.d.ts +4 -12
  11. package/dist/_internal/server/jobs/core/onOrderCreate.js +3 -3
  12. package/dist/_internal/server/jobs/core/onProductWrite.js +14 -2
  13. package/dist/_internal/shared/features/auctions/config.d.ts +1 -1
  14. package/dist/_internal/shared/features/auctions/config.js +1 -1
  15. package/dist/_internal/shared/features/auctions/schema.js +1 -1
  16. package/dist/_internal/shared/features/cart/schema.js +2 -2
  17. package/dist/_internal/shared/features/events/schema.js +1 -1
  18. package/dist/_internal/shared/features/orders/schema.js +1 -1
  19. package/dist/_internal/shared/features/products/schema.js +3 -3
  20. package/dist/_internal/shared/features/promotions/schema.js +3 -3
  21. package/dist/_internal/shared/fees/calculator.d.ts +6 -7
  22. package/dist/client.d.ts +4 -4
  23. package/dist/client.js +4 -2
  24. package/dist/constants/api-endpoints.d.ts +9 -6
  25. package/dist/constants/api-endpoints.js +3 -2
  26. package/dist/contracts/client-payment-gateway.d.ts +1 -2
  27. package/dist/features/about/components/AboutView.d.ts +6 -16
  28. package/dist/features/about/components/AboutView.js +3 -3
  29. package/dist/features/about/index.d.ts +2 -1
  30. package/dist/features/about/schemas/firestore.d.ts +47 -0
  31. package/dist/features/about/schemas/firestore.js +6 -0
  32. package/dist/features/about/schemas/index.d.ts +210 -0
  33. package/dist/features/about/schemas/index.js +45 -0
  34. package/dist/features/account/hooks/useProfile.js +3 -0
  35. package/dist/features/admin/components/AdminCarouselGroupEditorView.d.ts +6 -0
  36. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +50 -0
  37. package/dist/features/admin/components/AdminCartsView.js +16 -3
  38. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  39. package/dist/features/admin/components/AdminCouponsView.js +14 -4
  40. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -42
  41. package/dist/features/admin/components/AdminMediaView.js +1 -1
  42. package/dist/features/admin/components/AdminNotificationsView.js +31 -19
  43. package/dist/features/admin/components/AdminOrdersView.js +7 -0
  44. package/dist/features/admin/components/AdminPayoutsView.js +18 -3
  45. package/dist/features/admin/components/AdminProductsView.js +17 -2
  46. package/dist/features/admin/components/AdminReviewsView.js +16 -2
  47. package/dist/features/admin/components/AdminScammersView.js +7 -0
  48. package/dist/features/admin/components/AdminSectionsView.js +4 -0
  49. package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
  50. package/dist/features/admin/components/AdminSiteSettingsView.js +44 -2
  51. package/dist/features/admin/components/AdminStoreEditorView.d.ts +2 -1
  52. package/dist/features/admin/components/AdminStoreEditorView.js +4 -4
  53. package/dist/features/admin/components/AdminStoresView.js +1 -1
  54. package/dist/features/admin/components/AdminSupportTicketDetailView.js +23 -5
  55. package/dist/features/admin/components/AdminSupportTicketsView.js +20 -2
  56. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +4 -1
  57. package/dist/features/admin/components/AdminTesterChecklistView.js +8 -0
  58. package/dist/features/admin/components/index.d.ts +2 -0
  59. package/dist/features/admin/components/index.js +1 -0
  60. package/dist/features/admin/constants/filter-tabs.d.ts +55 -41
  61. package/dist/features/admin/constants/filter-tabs.js +55 -27
  62. package/dist/features/admin/schemas/firestore.d.ts +5 -0
  63. package/dist/features/auctions/actions/bid-actions.js +1 -1
  64. package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
  65. package/dist/features/auctions/components/AuctionsListView.js +8 -1
  66. package/dist/features/auth/components/LoginForm.js +2 -2
  67. package/dist/features/auth/components/RegisterForm.js +2 -2
  68. package/dist/features/auth/permissions/constants.d.ts +16 -0
  69. package/dist/features/auth/permissions/constants.js +53 -0
  70. package/dist/features/auth/schemas/firestore.js +1 -0
  71. package/dist/features/blog/components/BlogFilters.js +1 -1
  72. package/dist/features/cart/schemas/firestore.d.ts +1 -1
  73. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  74. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  75. package/dist/features/events/components/EventFilters.js +2 -0
  76. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  77. package/dist/features/layout/TitleBarLayout.d.ts +2 -2
  78. package/dist/features/layout/TitleBarLayout.js +4 -4
  79. package/dist/features/media/AvatarUpload.js +7 -3
  80. package/dist/features/media/MediaVideo.js +1 -1
  81. package/dist/features/media/finalize.d.ts +9 -13
  82. package/dist/features/media/finalize.js +23 -74
  83. package/dist/features/media/server.d.ts +1 -1
  84. package/dist/features/media/server.js +1 -1
  85. package/dist/features/orders/hooks/useOrders.js +16 -4
  86. package/dist/features/orders/schemas/firestore.d.ts +5 -5
  87. package/dist/features/payments/schemas/firestore.d.ts +2 -2
  88. package/dist/features/pre-orders/components/PreOrdersListView.js +7 -0
  89. package/dist/features/products/components/ArtStickersListView.js +5 -0
  90. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -1
  91. package/dist/features/products/components/ProductForm.js +14 -1
  92. package/dist/features/products/components/ProductsIndexPageView.js +7 -0
  93. package/dist/features/products/constants/action-defs.d.ts +1 -0
  94. package/dist/features/products/constants/action-defs.js +1 -0
  95. package/dist/features/products/schemas/firestore.d.ts +1 -1
  96. package/dist/features/products/schemas/product-templates.d.ts +1 -1
  97. package/dist/features/products/types/index.d.ts +4 -0
  98. package/dist/features/scams/schemas/index.js +2 -2
  99. package/dist/features/search/components/Search.js +3 -3
  100. package/dist/features/seller/components/SellerAuctionsView.js +27 -2
  101. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  102. package/dist/features/seller/components/SellerPayoutsView.js +24 -10
  103. package/dist/features/seller/components/SellerPreOrdersView.js +12 -4
  104. package/dist/features/seller/components/SellerPrizeDrawsView.js +23 -5
  105. package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
  106. package/dist/features/seller/components/SellerProductShell.js +1 -1
  107. package/dist/features/seller/components/SellerProductsView.js +8 -6
  108. package/dist/features/seller/components/SellerReviewsView.js +27 -6
  109. package/dist/features/seller/components/index.d.ts +0 -2
  110. package/dist/features/seller/components/index.js +0 -1
  111. package/dist/features/stores/components/StoreListingsGuideView.js +2 -1
  112. package/dist/features/stores/components/StoreProductsView.js +1 -1
  113. package/dist/features/stores/schemas/firestore.d.ts +11 -0
  114. package/dist/features/stores/schemas/firestore.js +5 -0
  115. package/dist/features/stores/schemas/index.d.ts +2 -2
  116. package/dist/features/tester/actions/checklist-item-actions.d.ts +6 -0
  117. package/dist/features/tester/actions/checklist-item-actions.js +2 -0
  118. package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +13 -2
  119. package/dist/features/tester/components/AdminTesterFeedbackListView.js +2 -1
  120. package/dist/features/tester/components/AdminTesterFeedbackReportView.js +9 -5
  121. package/dist/features/tester/components/TesterHubView.js +34 -21
  122. package/dist/features/tester/repository/tester-checklist-item.repository.js +1 -0
  123. package/dist/features/tester/repository/tester-checklist-response.repository.d.ts +18 -4
  124. package/dist/features/tester/repository/tester-checklist-response.repository.js +43 -8
  125. package/dist/features/tester/schemas/firestore.d.ts +8 -3
  126. package/dist/features/tester/schemas/firestore.js +6 -0
  127. package/dist/features/tester/seed-data/bids-tester-seed-data.d.ts +2 -0
  128. package/dist/features/tester/seed-data/bids-tester-seed-data.js +37 -0
  129. package/dist/features/tester/seed-data/coupons-tester-seed-data.d.ts +2 -0
  130. package/dist/features/tester/seed-data/coupons-tester-seed-data.js +76 -0
  131. package/dist/features/tester/seed-data/events-tester-seed-data.js +50 -2
  132. package/dist/features/tester/seed-data/index.d.ts +3 -0
  133. package/dist/features/tester/seed-data/index.js +3 -0
  134. package/dist/features/tester/seed-data/orders-tester-seed-data.d.ts +2 -0
  135. package/dist/features/tester/seed-data/orders-tester-seed-data.js +265 -0
  136. package/dist/features/tester/seed-data/products-tester-seed-data.js +213 -8
  137. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +294 -12
  138. package/dist/features/tester/utils/phases.d.ts +31 -0
  139. package/dist/features/tester/utils/phases.js +46 -0
  140. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
  141. package/dist/features/whatsapp-bot/types/index.d.ts +1 -1
  142. package/dist/features/wishlist/types/index.d.ts +3 -0
  143. package/dist/index.d.ts +11 -4
  144. package/dist/index.js +15 -7
  145. package/dist/next/api/routeHandler.js +6 -10
  146. package/dist/next/components/NotFoundView.js +2 -1
  147. package/dist/next/routing/route-map.d.ts +4 -12
  148. package/dist/next/routing/route-map.js +2 -4
  149. package/dist/providers/db-firebase/admin.d.ts +1 -0
  150. package/dist/providers/db-firebase/admin.js +1 -1
  151. package/dist/schemas/registry.d.ts +2 -2
  152. package/dist/seed/addresses-seed-data.js +18 -18
  153. package/dist/seed/bids-seed-data.js +4 -4
  154. package/dist/seed/blog-posts-seed-data.js +82 -82
  155. package/dist/seed/carousel-slides-seed-data.js +14 -10
  156. package/dist/seed/carousels-seed-data.js +3 -3
  157. package/dist/seed/cart-seed-data.js +92 -92
  158. package/dist/seed/claimed-coupons-seed-data.js +10 -10
  159. package/dist/seed/conversations-seed-data.js +75 -75
  160. package/dist/seed/coupon-usage-seed-data.js +12 -12
  161. package/dist/seed/coupons-seed-data.js +41 -41
  162. package/dist/seed/events-seed-data.js +105 -105
  163. package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
  164. package/dist/seed/grouped-listings-seed-data.js +79 -143
  165. package/dist/seed/history-seed-data.js +38 -38
  166. package/dist/seed/homepage-sections-seed-data.js +9 -9
  167. package/dist/seed/index.d.ts +1 -1
  168. package/dist/seed/index.js +1 -1
  169. package/dist/seed/manifest.js +4 -4
  170. package/dist/seed/notifications-seed-data.js +56 -56
  171. package/dist/seed/offers-seed-data.js +91 -91
  172. package/dist/seed/orders-seed-data.js +125 -106
  173. package/dist/seed/payouts-seed-data.js +42 -42
  174. package/dist/seed/products-auctions-seed-data.js +10 -2
  175. package/dist/seed/products-classifieds-seed-data.js +48 -5
  176. package/dist/seed/products-digital-codes-seed-data.js +48 -5
  177. package/dist/seed/products-live-items-seed-data.js +6 -1
  178. package/dist/seed/products-prize-draws-seed-data.js +58 -5
  179. package/dist/seed/products-standard-seed-data.js +40 -8
  180. package/dist/seed/reviews-seed-data.js +42 -23
  181. package/dist/seed/scammers-seed-data.js +22 -22
  182. package/dist/seed/sessions-seed-data.js +7 -7
  183. package/dist/seed/shipments-seed-data.js +10 -10
  184. package/dist/seed/site-settings-seed-data.js +82 -0
  185. package/dist/seed/store-addresses-seed-data.js +2 -2
  186. package/dist/seed/store-extensions-seed-data.js +93 -93
  187. package/dist/seed/stores-seed-data.js +2 -0
  188. package/dist/seed/support-tickets-seed-data.js +47 -47
  189. package/dist/seed/users-seed-data.js +55 -89
  190. package/dist/seed/wishlists-seed-data.js +22 -22
  191. package/dist/server.d.ts +2 -1
  192. package/dist/server.js +5 -5
  193. package/dist/styles.css +1 -1
  194. package/dist/tailwind-utilities.css +1 -1
  195. package/dist/ui/components/PageLoader.js +8 -3
  196. package/dist/ui/components/Select.d.ts +8 -1
  197. package/dist/ui/components/Select.js +2 -2
  198. package/dist/ui/components/SiteMark.d.ts +23 -0
  199. package/dist/ui/components/SiteMark.js +76 -0
  200. package/dist/ui/index.d.ts +2 -0
  201. package/dist/ui/index.js +1 -0
  202. package/dist/validation/schemas.d.ts +0 -2
  203. package/dist/validation/schemas.js +0 -2
  204. package/package.json +1 -1
  205. package/scripts/seed-cli.mjs +27 -19
@@ -24,6 +24,7 @@ export class TesterChecklistResponseRepository extends BaseRepository {
24
24
  checklistItemId: input.checklistItemId,
25
25
  groupKey: input.groupKey,
26
26
  pageKey: input.pageKey,
27
+ phase: input.phase,
27
28
  status: "new",
28
29
  };
29
30
  if (input.answer !== undefined)
@@ -55,9 +56,16 @@ export class TesterChecklistResponseRepository extends BaseRepository {
55
56
  status: "reviewed",
56
57
  });
57
58
  }
58
- /** Single collection scan (small table: testers x cases) — no join needed. */
59
+ /** Joins responses against the checklist catalog for human labels
60
+ * (groupLabel/pageLabel) — small tables (testers x cases, and the
61
+ * ~300-item catalog), so the extra read is cheap. `phase` itself is
62
+ * already denormalized onto the response doc, no join needed for it. */
59
63
  async getCoverageReport() {
60
- const snapshot = await this.db.collection(this.collection).get();
64
+ const [{ items }, snapshot] = await Promise.all([
65
+ testerChecklistItemRepository.list({ page: "1", pageSize: "1000" }),
66
+ this.db.collection(this.collection).get(),
67
+ ]);
68
+ const itemById = new Map(items.map((item) => [item.id, item]));
61
69
  const docs = snapshot.docs.map((doc) => this.mapDoc(doc));
62
70
  const byItem = new Map();
63
71
  const issues = [];
@@ -66,12 +74,18 @@ export class TesterChecklistResponseRepository extends BaseRepository {
66
74
  for (const doc of docs) {
67
75
  if (!doc.answer)
68
76
  continue;
77
+ const catalogItem = itemById.get(doc.checklistItemId);
78
+ const groupLabel = catalogItem?.groupLabel ?? doc.groupKey;
79
+ const pageLabel = catalogItem?.pageLabel ?? doc.pageKey;
69
80
  let entry = byItem.get(doc.checklistItemId);
70
81
  if (!entry) {
71
82
  entry = {
72
83
  checklistItemId: doc.checklistItemId,
73
84
  groupKey: doc.groupKey,
85
+ groupLabel,
74
86
  pageKey: doc.pageKey,
87
+ pageLabel,
88
+ phase: doc.phase,
75
89
  yesCount: 0,
76
90
  noCount: 0,
77
91
  totalAnswered: 0,
@@ -86,7 +100,12 @@ export class TesterChecklistResponseRepository extends BaseRepository {
86
100
  else {
87
101
  entry.noCount += 1;
88
102
  totalNo += 1;
89
- issues.push(doc);
103
+ issues.push({
104
+ ...doc,
105
+ groupLabel,
106
+ pageLabel,
107
+ label: catalogItem?.label ?? doc.checklistItemId,
108
+ });
90
109
  }
91
110
  }
92
111
  return {
@@ -99,8 +118,10 @@ export class TesterChecklistResponseRepository extends BaseRepository {
99
118
  * Markdown dump of every answered case, joined against the checklist item
100
119
  * catalog for the human-readable label/href — optimized for a future dev
101
120
  * (or Claude session) to read directly and go fix the reported issues.
102
- * Mirrors appkit/scripts/export-tester-feedback.mjs's CLI output exactly;
103
- * keep the two in sync.
121
+ * Grouped by phase (ascending), then group, then page — mirrors how the
122
+ * Tester Hub itself is organized. Mirrors
123
+ * appkit/scripts/export-tester-feedback.mjs's CLI output exactly; keep
124
+ * the two in sync.
104
125
  */
105
126
  async getMarkdownReport(siteOrigin) {
106
127
  const [items, snapshot] = await Promise.all([
@@ -114,14 +135,15 @@ export class TesterChecklistResponseRepository extends BaseRepository {
114
135
  const grouped = new Map();
115
136
  for (const r of responses) {
116
137
  const item = itemById.get(r.checklistItemId);
138
+ const phase = item?.phase ?? r.phase ?? 0;
117
139
  const groupLabel = item?.groupLabel ?? r.groupKey ?? "Unknown group";
118
140
  const pageLabel = item?.pageLabel ?? r.pageKey ?? "Unknown page";
119
- const key = `${groupLabel}␟${pageLabel}`;
141
+ const key = `${phase}␟${groupLabel}␟${pageLabel}`;
120
142
  if (!grouped.has(key))
121
- grouped.set(key, { groupLabel, pageLabel, items: [] });
143
+ grouped.set(key, { phase, groupLabel, pageLabel, items: [] });
122
144
  grouped.get(key).items.push({ ...r, label: item?.label ?? r.checklistItemId, href: item?.href });
123
145
  }
124
- const sortedGroups = Array.from(grouped.values()).sort((a, b) => a.groupLabel.localeCompare(b.groupLabel) || a.pageLabel.localeCompare(b.pageLabel));
146
+ const sortedGroups = Array.from(grouped.values()).sort((a, b) => a.phase - b.phase || a.groupLabel.localeCompare(b.groupLabel) || a.pageLabel.localeCompare(b.pageLabel));
125
147
  const issues = responses.filter((r) => r.answer === "no");
126
148
  const passingWithNotes = responses.filter((r) => r.answer === "yes" && r.comment?.trim());
127
149
  const lines = [];
@@ -138,10 +160,16 @@ export class TesterChecklistResponseRepository extends BaseRepository {
138
160
  lines.push("");
139
161
  }
140
162
  else {
163
+ let lastPhase = null;
141
164
  for (const group of sortedGroups) {
142
165
  const groupIssues = group.items.filter((r) => r.answer === "no");
143
166
  if (groupIssues.length === 0)
144
167
  continue;
168
+ if (group.phase !== lastPhase) {
169
+ lines.push(`## Phase ${group.phase}`);
170
+ lines.push("");
171
+ lastPhase = group.phase;
172
+ }
145
173
  lines.push(`### ${group.groupLabel} › ${group.pageLabel}`);
146
174
  lines.push("");
147
175
  for (const r of groupIssues) {
@@ -166,10 +194,16 @@ export class TesterChecklistResponseRepository extends BaseRepository {
166
194
  lines.push("");
167
195
  }
168
196
  else {
197
+ let lastPhase = null;
169
198
  for (const group of sortedGroups) {
170
199
  const groupNotes = group.items.filter((r) => r.answer === "yes" && r.comment?.trim());
171
200
  if (groupNotes.length === 0)
172
201
  continue;
202
+ if (group.phase !== lastPhase) {
203
+ lines.push(`## Phase ${group.phase}`);
204
+ lines.push("");
205
+ lastPhase = group.phase;
206
+ }
173
207
  lines.push(`### ${group.groupLabel} › ${group.pageLabel}`);
174
208
  lines.push("");
175
209
  for (const r of groupNotes) {
@@ -189,6 +223,7 @@ TesterChecklistResponseRepository.SIEVE_FIELDS = {
189
223
  checklistItemId: { canFilter: true, canSort: false },
190
224
  groupKey: { canFilter: true, canSort: true },
191
225
  pageKey: { canFilter: true, canSort: true },
226
+ phase: { canFilter: true, canSort: true },
192
227
  answer: { canFilter: true, canSort: false },
193
228
  status: { canFilter: true, canSort: false },
194
229
  createdAt: { canFilter: true, canSort: true },
@@ -15,16 +15,17 @@ export interface TesterChecklistItemDocument extends BaseDocument {
15
15
  description?: string;
16
16
  href?: string;
17
17
  order: number;
18
+ phase: number;
18
19
  isActive: boolean;
19
20
  searchTokens: string[];
20
21
  adminOnly?: boolean;
21
22
  }
22
23
  export declare const TESTER_CHECKLIST_ITEM_COLLECTION: "testerChecklistItems";
23
24
  export declare const TESTER_CHECKLIST_ITEM_ID_PREFIX: "checklist-";
24
- export declare const TESTER_CHECKLIST_ITEM_INDEXED_FIELDS: readonly ["groupKey", "pageKey", "order", "isActive", "searchTokens", "createdAt"];
25
+ export declare const TESTER_CHECKLIST_ITEM_INDEXED_FIELDS: readonly ["groupKey", "pageKey", "phase", "order", "isActive", "searchTokens", "createdAt"];
25
26
  export declare const DEFAULT_TESTER_CHECKLIST_ITEM_DATA: Partial<TesterChecklistItemDocument>;
26
27
  export type TesterChecklistItemCreateInput = Omit<TesterChecklistItemDocument, "id" | "createdAt" | "updatedAt" | "searchTokens">;
27
- export type TesterChecklistItemUpdateInput = Partial<Pick<TesterChecklistItemDocument, "groupKey" | "groupLabel" | "pageKey" | "pageLabel" | "label" | "description" | "href" | "order" | "isActive" | "adminOnly">>;
28
+ export type TesterChecklistItemUpdateInput = Partial<Pick<TesterChecklistItemDocument, "groupKey" | "groupLabel" | "pageKey" | "pageLabel" | "label" | "description" | "href" | "order" | "phase" | "isActive" | "adminOnly">>;
28
29
  export declare const testerChecklistItemQueryHelpers: {
29
30
  readonly byGroup: (groupKey: string) => readonly ["groupKey", "==", string];
30
31
  readonly byPage: (pageKey: string) => readonly ["pageKey", "==", string];
@@ -40,18 +41,20 @@ export interface TesterChecklistResponseDocument extends BaseDocument {
40
41
  checklistItemId: string;
41
42
  groupKey: string;
42
43
  pageKey: string;
44
+ phase: number;
43
45
  answer: TesterAnswer | null;
44
46
  comment?: string;
45
47
  screenshotUrl?: string;
46
48
  status: TesterFeedbackStatus;
47
49
  }
48
50
  export declare const TESTER_CHECKLIST_RESPONSE_COLLECTION: "testerChecklistResponses";
49
- export declare const TESTER_CHECKLIST_RESPONSE_INDEXED_FIELDS: readonly ["testerId", "checklistItemId", "groupKey", "pageKey", "answer", "status", "createdAt"];
51
+ export declare const TESTER_CHECKLIST_RESPONSE_INDEXED_FIELDS: readonly ["testerId", "checklistItemId", "groupKey", "pageKey", "phase", "answer", "status", "createdAt"];
50
52
  export declare const DEFAULT_TESTER_CHECKLIST_RESPONSE_DATA: Partial<TesterChecklistResponseDocument>;
51
53
  export declare function createChecklistResponseId(testerId: string, checklistItemId: string): string;
52
54
  export declare const testerChecklistResponseQueryHelpers: {
53
55
  readonly byTester: (testerId: string) => readonly ["testerId", "==", string];
54
56
  readonly byItem: (checklistItemId: string) => readonly ["checklistItemId", "==", string];
57
+ readonly byPhase: (phase: number) => readonly ["phase", "==", number];
55
58
  readonly byAnswer: (answer: TesterAnswer) => readonly ["answer", "==", TesterAnswer];
56
59
  readonly byStatus: (status: TesterFeedbackStatus) => readonly ["status", "==", TesterFeedbackStatus];
57
60
  };
@@ -65,6 +68,7 @@ export declare const TESTER_CHECKLIST_ITEM_FIELDS: {
65
68
  readonly DESCRIPTION: "description";
66
69
  readonly HREF: "href";
67
70
  readonly ORDER: "order";
71
+ readonly PHASE: "phase";
68
72
  readonly IS_ACTIVE: "isActive";
69
73
  readonly SEARCH_TOKENS: "searchTokens";
70
74
  readonly ADMIN_ONLY: "adminOnly";
@@ -78,6 +82,7 @@ export declare const TESTER_CHECKLIST_RESPONSE_FIELDS: {
78
82
  readonly CHECKLIST_ITEM_ID: "checklistItemId";
79
83
  readonly GROUP_KEY: "groupKey";
80
84
  readonly PAGE_KEY: "pageKey";
85
+ readonly PHASE: "phase";
81
86
  readonly ANSWER: "answer";
82
87
  readonly COMMENT: "comment";
83
88
  readonly SCREENSHOT_URL: "screenshotUrl";
@@ -11,6 +11,7 @@ export const TESTER_CHECKLIST_ITEM_ID_PREFIX = "checklist-";
11
11
  export const TESTER_CHECKLIST_ITEM_INDEXED_FIELDS = [
12
12
  "groupKey",
13
13
  "pageKey",
14
+ "phase",
14
15
  "order",
15
16
  "isActive",
16
17
  "searchTokens",
@@ -18,6 +19,7 @@ export const TESTER_CHECKLIST_ITEM_INDEXED_FIELDS = [
18
19
  ];
19
20
  export const DEFAULT_TESTER_CHECKLIST_ITEM_DATA = {
20
21
  order: 0,
22
+ phase: 1,
21
23
  isActive: true,
22
24
  searchTokens: [],
23
25
  adminOnly: false,
@@ -45,6 +47,7 @@ export const TESTER_CHECKLIST_RESPONSE_INDEXED_FIELDS = [
45
47
  "checklistItemId",
46
48
  "groupKey",
47
49
  "pageKey",
50
+ "phase",
48
51
  "answer",
49
52
  "status",
50
53
  "createdAt",
@@ -59,6 +62,7 @@ export function createChecklistResponseId(testerId, checklistItemId) {
59
62
  export const testerChecklistResponseQueryHelpers = {
60
63
  byTester: (testerId) => ["testerId", "==", testerId],
61
64
  byItem: (checklistItemId) => ["checklistItemId", "==", checklistItemId],
65
+ byPhase: (phase) => ["phase", "==", phase],
62
66
  byAnswer: (answer) => ["answer", "==", answer],
63
67
  byStatus: (status) => ["status", "==", status],
64
68
  };
@@ -73,6 +77,7 @@ export const TESTER_CHECKLIST_ITEM_FIELDS = {
73
77
  DESCRIPTION: "description",
74
78
  HREF: "href",
75
79
  ORDER: "order",
80
+ PHASE: "phase",
76
81
  IS_ACTIVE: "isActive",
77
82
  SEARCH_TOKENS: "searchTokens",
78
83
  ADMIN_ONLY: "adminOnly",
@@ -86,6 +91,7 @@ export const TESTER_CHECKLIST_RESPONSE_FIELDS = {
86
91
  CHECKLIST_ITEM_ID: "checklistItemId",
87
92
  GROUP_KEY: "groupKey",
88
93
  PAGE_KEY: "pageKey",
94
+ PHASE: "phase",
89
95
  ANSWER: "answer",
90
96
  COMMENT: "comment",
91
97
  SCREENSHOT_URL: "screenshotUrl",
@@ -0,0 +1,2 @@
1
+ import type { BidDocument } from "../../auctions/schemas/firestore";
2
+ export declare const bidsTesterSeedData: Partial<BidDocument>[];
@@ -0,0 +1,37 @@
1
+ /*
2
+ * WHY: Shared tester sandbox — one winning bid on the already-ended auction-tester-sandbox-won
3
+ * (kept separate from the still-biddable auction-tester-sandbox-1 so testers can still
4
+ * place a live bid on the latter) so testers (and the paired orders-tester-seed-data.ts
5
+ * auction-win order) can exercise the "winning an auction creates a payable order" flow.
6
+ * Auto-expires in 7 days, cascading with the parent auction product.
7
+ * WHAT: Exports bidsTesterSeedData — 1 Partial<BidDocument> for the seed runner.
8
+ *
9
+ * EXPORTS:
10
+ * bidsTesterSeedData — Array of 1 Partial<BidDocument> for the seed runner
11
+ *
12
+ * @tag domain:auctions,bids,tester
13
+ * @tag layer:seed
14
+ * @tag pattern:none
15
+ * @tag access:server-only
16
+ * @tag consumers:seed/index.ts,seed-cli.mjs
17
+ * @tag sideEffects:none
18
+ */
19
+ const NOW = new Date();
20
+ const daysAgo = (n) => new Date(NOW.getTime() - n * 86400000);
21
+ export const bidsTesterSeedData = [
22
+ {
23
+ id: "bid-tester-sandbox-won-tester-qa",
24
+ productId: "auction-tester-sandbox-won",
25
+ productTitle: "Test Auction — Already Won",
26
+ userId: "user-tester-qa",
27
+ userName: "QA Tester",
28
+ userEmail: "tester@letitrip.in",
29
+ bidAmount: 15000,
30
+ currency: "INR",
31
+ status: "won",
32
+ isWinning: true,
33
+ bidDate: daysAgo(1),
34
+ createdAt: daysAgo(1),
35
+ updatedAt: daysAgo(1),
36
+ },
37
+ ];
@@ -0,0 +1,2 @@
1
+ import type { CouponDocument } from "../../promotions/schemas";
2
+ export declare const couponsTesterSeedData: Partial<CouponDocument>[];
@@ -0,0 +1,76 @@
1
+ /*
2
+ * WHY: Shared tester sandbox — 3 disposable test coupons so testers can exercise
3
+ * coupon apply/reject edge cases end to end: a perUserLimit:1 admin coupon (to
4
+ * verify the second-use rejection), an already-expired admin coupon (to verify
5
+ * the expiry rejection), and a seller-scope coupon on store-tester-sandbox.
6
+ * NOTE: CouponDocument does not currently carry isTestData/testDataExpiresAt
7
+ * (unlike categories/stores/products/blogPosts/events) — testerSandboxCleanup
8
+ * does not cascade-delete these. They're small, static, and harmless to leave;
9
+ * extending the cleanup script to cover coupons is a follow-up, not blocking.
10
+ * WHAT: Exports couponsTesterSeedData — 3 Partial<CouponDocument> for the seed runner.
11
+ *
12
+ * EXPORTS:
13
+ * couponsTesterSeedData — Array of 3 Partial<CouponDocument> for the seed runner
14
+ *
15
+ * @tag domain:coupons,tester
16
+ * @tag layer:seed
17
+ * @tag pattern:none
18
+ * @tag access:server-only
19
+ * @tag consumers:seed/index.ts,seed-cli.mjs
20
+ * @tag sideEffects:none
21
+ */
22
+ import { COUPON_FIELDS } from "../../../constants/field-names";
23
+ const NOW = new Date();
24
+ const daysAgo = (n) => new Date(NOW.getTime() - n * 86400000);
25
+ const daysAhead = (n) => new Date(NOW.getTime() + n * 86400000);
26
+ export const couponsTesterSeedData = [
27
+ {
28
+ id: "coupon-tester-sandbox-limited",
29
+ code: "TESTERLIMITED",
30
+ name: "Tester Sandbox — One Use Per Tester",
31
+ description: "Disposable test coupon: 10% off, capped at one use per tester. Use it twice to verify the second attempt is rejected.",
32
+ type: COUPON_FIELDS.TYPE_VALUES.PERCENTAGE,
33
+ scope: COUPON_FIELDS.SCOPE_VALUES.ADMIN,
34
+ discount: { value: 10, maxDiscount: 100, minPurchase: 100 },
35
+ usage: { totalLimit: undefined, perUserLimit: 1, currentUsage: 0 },
36
+ validity: { startDate: daysAgo(1), endDate: daysAhead(7), isActive: true },
37
+ restrictions: { firstTimeUserOnly: false, combineWithSellerCoupons: true },
38
+ createdBy: "user-admin-letitrip",
39
+ createdAt: daysAgo(1),
40
+ updatedAt: daysAgo(1),
41
+ stats: { totalUses: 0, totalRevenue: 0, totalDiscount: 0 },
42
+ },
43
+ {
44
+ id: "coupon-tester-sandbox-expired",
45
+ code: "TESTEREXPIRED",
46
+ name: "Tester Sandbox — Already Expired",
47
+ description: "Disposable test coupon that already expired — applying it at checkout should show a specific expiry rejection.",
48
+ type: COUPON_FIELDS.TYPE_VALUES.FIXED,
49
+ scope: COUPON_FIELDS.SCOPE_VALUES.ADMIN,
50
+ discount: { value: 50, maxDiscount: 50, minPurchase: 100 },
51
+ usage: { totalLimit: undefined, perUserLimit: 5, currentUsage: 0 },
52
+ validity: { startDate: daysAgo(30), endDate: daysAgo(1), isActive: true },
53
+ restrictions: { firstTimeUserOnly: false, combineWithSellerCoupons: true },
54
+ createdBy: "user-admin-letitrip",
55
+ createdAt: daysAgo(30),
56
+ updatedAt: daysAgo(30),
57
+ stats: { totalUses: 0, totalRevenue: 0, totalDiscount: 0 },
58
+ },
59
+ {
60
+ id: "coupon-tester-sandbox-seller",
61
+ code: "TESTERSTORE",
62
+ name: "Tester Sandbox Store — 5% Off",
63
+ description: "Disposable seller-scope test coupon on the tester sandbox store.",
64
+ type: COUPON_FIELDS.TYPE_VALUES.PERCENTAGE,
65
+ scope: COUPON_FIELDS.SCOPE_VALUES.SELLER,
66
+ storeId: "store-tester-sandbox",
67
+ discount: { value: 5, maxDiscount: 50, minPurchase: 0 },
68
+ usage: { totalLimit: undefined, perUserLimit: 3, currentUsage: 0 },
69
+ validity: { startDate: daysAgo(1), endDate: daysAhead(7), isActive: true },
70
+ restrictions: { firstTimeUserOnly: false, combineWithSellerCoupons: true },
71
+ createdBy: "user-admin-letitrip",
72
+ createdAt: daysAgo(1),
73
+ updatedAt: daysAgo(1),
74
+ stats: { totalUses: 0, totalRevenue: 0, totalDiscount: 0 },
75
+ },
76
+ ];
@@ -17,6 +17,8 @@
17
17
  import { EVENT_FIELDS } from "../../../constants/field-names";
18
18
  import { seedExtMedia } from "../../../seed/_helpers/media";
19
19
  import { testDataExpiresAt } from "./tester-ttl";
20
+ const TEST_EVENT_COVER_ALT = "Test event cover";
21
+ const TEST_RAFFLE_PRIZE = "Test prize — not a real reward";
20
22
  export const eventsTesterSeedData = [
21
23
  {
22
24
  id: "event-tester-sandbox-spin",
@@ -27,11 +29,11 @@ export const eventsTesterSeedData = [
27
29
  status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
28
30
  startsAt: new Date(),
29
31
  endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
30
- coverImage: { type: "image", url: seedExtMedia("https://picsum.photos/seed/event-cover-tester-sandbox-spin-20260101/1200/600"), alt: "Test event cover" },
32
+ coverImage: { type: "image", url: seedExtMedia("https://picsum.photos/seed/event-cover-tester-sandbox-spin-20260101/1200/600"), alt: TEST_EVENT_COVER_ALT },
31
33
  tags: ["test"],
32
34
  hasRaffle: true,
33
35
  raffleType: "open_raffle",
34
- rafflePrize: "Test prize — not a real reward",
36
+ rafflePrize: TEST_RAFFLE_PRIZE,
35
37
  raffleEntryCount: 0,
36
38
  spinPrizes: [
37
39
  { id: "spin-tester-win", label: "You Win!", weight: 50, isActive: true },
@@ -47,4 +49,50 @@ export const eventsTesterSeedData = [
47
49
  createdAt: new Date(),
48
50
  updatedAt: new Date(),
49
51
  },
52
+ {
53
+ id: "event-tester-sandbox-top-scorers",
54
+ slug: "tester-sandbox-top-scorers",
55
+ type: EVENT_FIELDS.TYPE_VALUES.RAFFLE,
56
+ title: "Tester Sandbox — Top Scorers Raffle",
57
+ description: "Disposable test event for the tester QA program. Verify top_n_scorers raffle entry and the leaderboard.",
58
+ status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
59
+ startsAt: new Date(),
60
+ endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
61
+ coverImage: { type: "image", url: seedExtMedia("https://picsum.photos/seed/event-cover-tester-sandbox-top-scorers-20260101/1200/600"), alt: TEST_EVENT_COVER_ALT },
62
+ tags: ["test"],
63
+ hasRaffle: true,
64
+ raffleType: "top_n_scorers",
65
+ raffleTopN: 3,
66
+ rafflePrize: TEST_RAFFLE_PRIZE,
67
+ raffleEntryCount: 0,
68
+ stats: { totalEntries: 0, approvedEntries: 0, flaggedEntries: 0 },
69
+ createdBy: "user-admin-letitrip",
70
+ isTestData: true,
71
+ testDataExpiresAt: testDataExpiresAt(),
72
+ createdAt: new Date(),
73
+ updatedAt: new Date(),
74
+ },
75
+ {
76
+ id: "event-tester-sandbox-top-participants",
77
+ slug: "tester-sandbox-top-participants",
78
+ type: EVENT_FIELDS.TYPE_VALUES.RAFFLE,
79
+ title: "Tester Sandbox — Top Participants Raffle",
80
+ description: "Disposable test event for the tester QA program. Verify top_n_participants raffle entry.",
81
+ status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
82
+ startsAt: new Date(),
83
+ endsAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
84
+ coverImage: { type: "image", url: seedExtMedia("https://picsum.photos/seed/event-cover-tester-sandbox-top-participants-20260101/1200/600"), alt: TEST_EVENT_COVER_ALT },
85
+ tags: ["test"],
86
+ hasRaffle: true,
87
+ raffleType: "top_n_participants",
88
+ raffleTopN: 5,
89
+ rafflePrize: TEST_RAFFLE_PRIZE,
90
+ raffleEntryCount: 0,
91
+ stats: { totalEntries: 0, approvedEntries: 0, flaggedEntries: 0 },
92
+ createdBy: "user-admin-letitrip",
93
+ isTestData: true,
94
+ testDataExpiresAt: testDataExpiresAt(),
95
+ createdAt: new Date(),
96
+ updatedAt: new Date(),
97
+ },
50
98
  ];
@@ -4,3 +4,6 @@ export { categoriesTesterSeedData } from "./categories-tester-seed-data";
4
4
  export { productsTesterSeedData } from "./products-tester-seed-data";
5
5
  export { blogTesterSeedData } from "./blog-tester-seed-data";
6
6
  export { eventsTesterSeedData } from "./events-tester-seed-data";
7
+ export { couponsTesterSeedData } from "./coupons-tester-seed-data";
8
+ export { bidsTesterSeedData } from "./bids-tester-seed-data";
9
+ export { ordersTesterSeedData } from "./orders-tester-seed-data";
@@ -4,3 +4,6 @@ export { categoriesTesterSeedData } from "./categories-tester-seed-data";
4
4
  export { productsTesterSeedData } from "./products-tester-seed-data";
5
5
  export { blogTesterSeedData } from "./blog-tester-seed-data";
6
6
  export { eventsTesterSeedData } from "./events-tester-seed-data";
7
+ export { couponsTesterSeedData } from "./coupons-tester-seed-data";
8
+ export { bidsTesterSeedData } from "./bids-tester-seed-data";
9
+ export { ordersTesterSeedData } from "./orders-tester-seed-data";
@@ -0,0 +1,2 @@
1
+ import type { OrderDocument } from "../../orders/schemas/firestore";
2
+ export declare const ordersTesterSeedData: Partial<OrderDocument>[];