@mohasinac/appkit 4.1.1 → 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 (187) 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/tester-checklist-seed-data.js +21 -9
  128. package/dist/features/tester/utils/phases.d.ts +31 -0
  129. package/dist/features/tester/utils/phases.js +46 -0
  130. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +1 -1
  131. package/dist/features/whatsapp-bot/types/index.d.ts +1 -1
  132. package/dist/features/wishlist/types/index.d.ts +3 -0
  133. package/dist/index.d.ts +11 -4
  134. package/dist/index.js +15 -7
  135. package/dist/next/components/NotFoundView.js +2 -1
  136. package/dist/next/routing/route-map.d.ts +4 -12
  137. package/dist/next/routing/route-map.js +2 -4
  138. package/dist/providers/db-firebase/admin.d.ts +1 -0
  139. package/dist/providers/db-firebase/admin.js +1 -1
  140. package/dist/schemas/registry.d.ts +2 -2
  141. package/dist/seed/addresses-seed-data.js +18 -18
  142. package/dist/seed/bids-seed-data.js +4 -4
  143. package/dist/seed/blog-posts-seed-data.js +82 -82
  144. package/dist/seed/carousel-slides-seed-data.js +14 -10
  145. package/dist/seed/carousels-seed-data.js +3 -3
  146. package/dist/seed/cart-seed-data.js +92 -92
  147. package/dist/seed/claimed-coupons-seed-data.js +10 -10
  148. package/dist/seed/conversations-seed-data.js +75 -75
  149. package/dist/seed/coupon-usage-seed-data.js +12 -12
  150. package/dist/seed/coupons-seed-data.js +41 -41
  151. package/dist/seed/events-seed-data.js +105 -105
  152. package/dist/seed/grouped-listings-seed-data.d.ts +2 -137
  153. package/dist/seed/grouped-listings-seed-data.js +79 -143
  154. package/dist/seed/history-seed-data.js +38 -38
  155. package/dist/seed/homepage-sections-seed-data.js +9 -9
  156. package/dist/seed/notifications-seed-data.js +56 -56
  157. package/dist/seed/offers-seed-data.js +91 -91
  158. package/dist/seed/orders-seed-data.js +121 -106
  159. package/dist/seed/payouts-seed-data.js +42 -42
  160. package/dist/seed/products-auctions-seed-data.js +10 -2
  161. package/dist/seed/products-standard-seed-data.js +40 -8
  162. package/dist/seed/reviews-seed-data.js +42 -23
  163. package/dist/seed/scammers-seed-data.js +22 -22
  164. package/dist/seed/sessions-seed-data.js +7 -7
  165. package/dist/seed/shipments-seed-data.js +10 -10
  166. package/dist/seed/site-settings-seed-data.js +82 -0
  167. package/dist/seed/store-addresses-seed-data.js +2 -2
  168. package/dist/seed/store-extensions-seed-data.js +93 -93
  169. package/dist/seed/stores-seed-data.js +2 -0
  170. package/dist/seed/support-tickets-seed-data.js +47 -47
  171. package/dist/seed/users-seed-data.js +55 -89
  172. package/dist/seed/wishlists-seed-data.js +22 -22
  173. package/dist/server.d.ts +2 -1
  174. package/dist/server.js +5 -5
  175. package/dist/styles.css +1 -1
  176. package/dist/tailwind-utilities.css +1 -1
  177. package/dist/ui/components/PageLoader.js +8 -3
  178. package/dist/ui/components/Select.d.ts +8 -1
  179. package/dist/ui/components/Select.js +2 -2
  180. package/dist/ui/components/SiteMark.d.ts +23 -0
  181. package/dist/ui/components/SiteMark.js +76 -0
  182. package/dist/ui/index.d.ts +2 -0
  183. package/dist/ui/index.js +1 -0
  184. package/dist/validation/schemas.d.ts +0 -2
  185. package/dist/validation/schemas.js +0 -2
  186. package/package.json +1 -1
  187. package/scripts/seed-cli.mjs +17 -15
@@ -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",
@@ -17,6 +17,7 @@
17
17
  * @tag consumers:seed/index.ts,seed/runner.ts
18
18
  * @tag sideEffects:none
19
19
  */
20
+ import { assignDefaultPhases } from "../utils/phases";
20
21
  function group(groupKey, groupLabel, pages, opts) {
21
22
  const items = [];
22
23
  pages.forEach((page, pageIdx) => {
@@ -38,17 +39,23 @@ function group(groupKey, groupLabel, pages, opts) {
38
39
  });
39
40
  return items;
40
41
  }
41
- export const testerChecklistSeedData = [
42
+ /**
43
+ * Array order below IS the intended catalog order (groups concatenated via
44
+ * spread, in authoring order) — `assignDefaultPhases` walks it directly
45
+ * rather than sorting by `order`, since `order` restarts at 0 within each
46
+ * group and is not globally unique across groups.
47
+ */
48
+ const rawTesterChecklistItems = [
42
49
  ...group("account-auth", "Account & Auth", [
43
50
  {
44
51
  pageKey: "signup-login",
45
52
  pageLabel: "Signup & Login",
46
53
  cases: [
47
- { key: "email-signup", label: "Sign up with email works", href: "/register" },
48
- { key: "google-oauth", label: "Sign up / log in with Google works", href: "/login" },
54
+ { key: "email-signup", label: "Sign up with email works", href: "/auth/register" },
55
+ { key: "google-oauth", label: "Sign up / log in with Google works", href: "/auth/login" },
49
56
  { key: "google-link-existing", label: "Linking Google sign-in to an existing email/password account works" },
50
57
  { key: "google-popup-blocked-fallback", label: "If the Google sign-in popup is blocked, the fallback (RTDB signal + postMessage) still completes sign-in" },
51
- { key: "login", label: "Log in with email + password works", href: "/login" },
58
+ { key: "login", label: "Log in with email + password works", href: "/auth/login" },
52
59
  { key: "logout", label: "Log out works and clears the session" },
53
60
  { key: "email-verify", label: "Email verification link works" },
54
61
  { key: "password-reset", label: "Forgot-password / reset-password flow works" },
@@ -110,7 +117,7 @@ export const testerChecklistSeedData = [
110
117
  { key: "add-to-cart", label: "Add to cart works from the product page" },
111
118
  { key: "add-to-cart-out-of-stock", label: "Add to cart is disabled/blocked once a listing's stock reaches zero" },
112
119
  { key: "add-to-cart-max-quantity", label: "Increasing quantity in the cart is capped at the listing's available stock, with a clear message" },
113
- { key: "checkout-flow", label: "Checkout flow completes without errors", href: "/cart" },
120
+ { key: "checkout-flow", label: "Checkout flow completes without errors", href: "/checkout" },
114
121
  { key: "checkout-order-review", label: "The order-review step before payment shows correct items, quantities, addresses, and totals" },
115
122
  { key: "checkout-multi-seller-split", label: "A cart with items from multiple sellers correctly splits into separate orders at checkout" },
116
123
  { key: "shipping-address", label: "Selecting/adding a shipping address works" },
@@ -147,7 +154,7 @@ export const testerChecklistSeedData = [
147
154
  pageKey: "wishlist-history",
148
155
  pageLabel: "Wishlist & History",
149
156
  cases: [
150
- { key: "add-wishlist-pdp", label: "Adding a product to the wishlist from the product detail page works", href: "/user/wishlist" },
157
+ { key: "add-wishlist-pdp", label: "Adding a product to the wishlist from the product detail page works", href: "/wishlist" },
151
158
  { key: "add-wishlist-card", label: "Adding a product to the wishlist from a listing card (checkbox/long-press) works on both listing and search pages" },
152
159
  { key: "remove-wishlist", label: "Removing a product from the wishlist works" },
153
160
  { key: "wishlist-persists-guest-to-login", label: "Wishlist items added as a guest are preserved after logging in" },
@@ -156,7 +163,7 @@ export const testerChecklistSeedData = [
156
163
  { key: "wishlist-across-listing-types", label: "Auctions and pre-orders (not just standard products) can be added to and viewed correctly in the wishlist" },
157
164
  { key: "wishlist-price-drop-accuracy", label: "A wishlist item's displayed price matches the product's current price, not a stale snapshot" },
158
165
  { key: "wishlist-sold-out-item", label: "A wishlist item whose product later sells out or is removed still displays gracefully (no crash) with an appropriate indicator" },
159
- { key: "wishlist-empty-state", label: "The empty-wishlist state renders correctly with no items", href: "/user/wishlist" },
166
+ { key: "wishlist-empty-state", label: "The empty-wishlist state renders correctly with no items", href: "/wishlist" },
160
167
  { key: "wishlist-add-to-cart-from-list", label: "Adding a wishlist item directly to the cart from the wishlist page works" },
161
168
  { key: "view-history", label: "Recently viewed history shows accurate items in most-recent-first order", href: "/user/history" },
162
169
  { key: "history-revisit-reorders", label: "Re-visiting a product already in history removes the old entry and moves it to the front, rather than duplicating it" },
@@ -311,7 +318,7 @@ export const testerChecklistSeedData = [
311
318
  { key: "seller-messages", label: "Seller messages list and thread view both work", href: "/store/messages" },
312
319
  { key: "seller-fulfillment-queue", label: "Seller fulfillment queue shows accurate pending items", href: "/store/fulfillment" },
313
320
  { key: "seller-print-center", label: "Seller print-center generates labels/invoices correctly", href: "/store/print-center" },
314
- { key: "seller-inventory-print", label: "Seller inventory print view works", href: "/store/inventory/print" },
321
+ { key: "seller-inventory-print", label: "Seller inventory print view works", href: "/store/print-center" },
315
322
  ],
316
323
  },
317
324
  {
@@ -514,7 +521,7 @@ export const testerChecklistSeedData = [
514
521
  pageKey: "auth-error-pages",
515
522
  pageLabel: "Remaining Auth & Error Pages",
516
523
  cases: [
517
- { key: "register-page", label: "The register page loads and account creation works", href: "/register" },
524
+ { key: "register-page", label: "The register page loads and account creation works", href: "/auth/register" },
518
525
  { key: "forgot-reset-password-pages", label: "Forgot-password and reset-password pages both work" },
519
526
  { key: "verify-email-page", label: "The verify-email page correctly confirms a pending verification" },
520
527
  { key: "oauth-loading-redirect", label: "The OAuth-loading redirect page transitions correctly after a Google sign-in" },
@@ -676,3 +683,8 @@ export const testerChecklistSeedData = [
676
683
  },
677
684
  ], { adminOnly: true }),
678
685
  ];
686
+ const defaultPhases = assignDefaultPhases(rawTesterChecklistItems);
687
+ export const testerChecklistSeedData = rawTesterChecklistItems.map((item, index) => ({
688
+ ...item,
689
+ phase: defaultPhases[index],
690
+ }));
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Computes default `phase` numbers for the tester checklist catalog.
3
+ *
4
+ * `phase` is a real, stored, admin-editable field on `TesterChecklistItemDocument`
5
+ * (see schemas/firestore.ts) — not something recomputed on every read. This
6
+ * module only supplies the INITIAL assignment: given the catalog in its
7
+ * existing groupKey/pageKey/order sequence, bucket whole pages together into
8
+ * phases of roughly `targetPhaseSize` items each (never splitting a single
9
+ * page's items across two phases), so a tester works through ~10-50 cases
10
+ * per session instead of the full catalog at once.
11
+ *
12
+ * Used once at seed-authoring time (tester-checklist-seed-data.ts) and by
13
+ * the one-off Firestore backfill for already-seeded items that predate the
14
+ * `phase` field. After that, every read path (TesterHubView, admin results
15
+ * views, the markdown report) just groups by the stored `item.phase` value —
16
+ * no chunking logic at read time.
17
+ */
18
+ export interface TesterPhaseAssignable {
19
+ groupKey: string;
20
+ pageKey: string;
21
+ }
22
+ /** Target item count per phase — real phase sizes vary a little around this
23
+ * since a page's items are never split across two phases. */
24
+ export declare const DEFAULT_TESTER_PHASE_SIZE = 25;
25
+ /**
26
+ * Returns a same-length array of 1-based phase numbers, one per input item,
27
+ * computed by greedily packing whole pages (consecutive runs of the same
28
+ * groupKey+pageKey) into phases of ~`targetPhaseSize` items. `items` MUST
29
+ * already be in catalog order (e.g. sorted by the `order` field).
30
+ */
31
+ export declare function assignDefaultPhases<T extends TesterPhaseAssignable>(itemsInCatalogOrder: T[], targetPhaseSize?: number): number[];
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Computes default `phase` numbers for the tester checklist catalog.
3
+ *
4
+ * `phase` is a real, stored, admin-editable field on `TesterChecklistItemDocument`
5
+ * (see schemas/firestore.ts) — not something recomputed on every read. This
6
+ * module only supplies the INITIAL assignment: given the catalog in its
7
+ * existing groupKey/pageKey/order sequence, bucket whole pages together into
8
+ * phases of roughly `targetPhaseSize` items each (never splitting a single
9
+ * page's items across two phases), so a tester works through ~10-50 cases
10
+ * per session instead of the full catalog at once.
11
+ *
12
+ * Used once at seed-authoring time (tester-checklist-seed-data.ts) and by
13
+ * the one-off Firestore backfill for already-seeded items that predate the
14
+ * `phase` field. After that, every read path (TesterHubView, admin results
15
+ * views, the markdown report) just groups by the stored `item.phase` value —
16
+ * no chunking logic at read time.
17
+ */
18
+ /** Target item count per phase — real phase sizes vary a little around this
19
+ * since a page's items are never split across two phases. */
20
+ export const DEFAULT_TESTER_PHASE_SIZE = 25;
21
+ /**
22
+ * Returns a same-length array of 1-based phase numbers, one per input item,
23
+ * computed by greedily packing whole pages (consecutive runs of the same
24
+ * groupKey+pageKey) into phases of ~`targetPhaseSize` items. `items` MUST
25
+ * already be in catalog order (e.g. sorted by the `order` field).
26
+ */
27
+ export function assignDefaultPhases(itemsInCatalogOrder, targetPhaseSize = DEFAULT_TESTER_PHASE_SIZE) {
28
+ const phaseNumbers = new Array(itemsInCatalogOrder.length);
29
+ let currentPhase = 1;
30
+ let currentPhaseCount = 0;
31
+ let lastPageKey = null;
32
+ for (let i = 0; i < itemsInCatalogOrder.length; i++) {
33
+ const item = itemsInCatalogOrder[i];
34
+ const pageId = `${item.groupKey}␟${item.pageKey}`;
35
+ const isNewPage = pageId !== lastPageKey;
36
+ // Only allow a phase boundary between pages, never mid-page.
37
+ if (isNewPage && currentPhaseCount >= targetPhaseSize) {
38
+ currentPhase += 1;
39
+ currentPhaseCount = 0;
40
+ }
41
+ phaseNumbers[i] = currentPhase;
42
+ currentPhaseCount += 1;
43
+ lastPageKey = pageId;
44
+ }
45
+ return phaseNumbers;
46
+ }
@@ -166,7 +166,7 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
166
166
  buyerName: "Ravi K.",
167
167
  firstItemName: "Charizard PSA 9",
168
168
  additionalItemCount: 2,
169
- totalAmount: 450000,
169
+ totalAmount: 4500,
170
170
  orderId: "order-3-20260510-a1b2c3",
171
171
  }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-2", color: "primary", size: "sm", weight: "semibold", children: "Catalog Preview" }), _jsx(Text, { className: "mb-4", color: "muted", size: "xs", children: "This is how your products appear in the WhatsApp Catalog when a buyer taps \"View Catalog\" in the chat. Only published standard products are included." }), _jsxs(Div, { className: `${__O.hidden} bg-[var(--appkit-color-whatsapp-bg)] bg-[var(--appkit-color-surface-elevated)] ${__P.p3}`, rounded: "xl", border: "default", children: [_jsxs(Row, { gap: "sm", align: "center", className: "mb-3", children: [_jsx(Row, { className: "w-8 h-8 bg-[var(--appkit-color-whatsapp)]", align: "center", justify: "center", rounded: "full", children: _jsx(Text, { color: "inverse", size: "xs", weight: "bold", children: "W" }) }), _jsxs(Div, { children: [_jsx(Text, { size: "xs", weight: "semibold", color: "primary", children: cfg?.connected ? "Your Store" : "Store Name" }), _jsx(Text, { className: "text-[10px]", color: "muted", children: "WhatsApp Business" })] })] }), _jsx(Div, { layout: "grid", gap: "2", className: "grid-cols-2", children: SAMPLE_CATALOG_ITEMS.map((item) => (_jsxs(Div, { surface: "card", className: `${__O.hidden}`, children: [_jsx(Row, { className: "aspect-square", surface: "subtle", align: "center", justify: "center", children: _jsx(Text, { size: "2xl", children: item.emoji }) }), _jsxs(Div, { padding: "xs", children: [_jsx(Text, { className: "line-clamp-2 leading-tight", color: "primary", size: "xs", weight: "medium", children: item.name }), _jsx(Text, { className: "text-[var(--appkit-color-whatsapp)] mt-0.5", size: "xs", weight: "semibold", children: item.price })] })] }, item.id))) }), _jsx(Div, { className: "mt-3 text-center", children: _jsx(Text, { className: "text-[10px]", color: "muted", children: cfg?.lastSyncCount
172
172
  ? `${cfg.lastSyncCount} products synced to catalog`
@@ -85,7 +85,7 @@ export interface PurchaseAnnouncementInput {
85
85
  firstItemName: string;
86
86
  /** 0 if only one item in the order */
87
87
  additionalItemCount: number;
88
- /** Total order amount in paise */
88
+ /** Total order amount in decimal rupees */
89
89
  totalAmount: number;
90
90
  orderId: string;
91
91
  }
@@ -26,6 +26,9 @@ export interface WishlistProductData {
26
26
  isFeatured?: boolean;
27
27
  /** Canonical listing-kind discriminator (SB1-G Phase 4). */
28
28
  listingType?: ListingType;
29
+ /** Already present on the wire — GET /api/user/wishlist spreads the full
30
+ * ProductDocument into `product`, this was just untyped. */
31
+ isSold?: boolean;
29
32
  }
30
33
  /** WishlistItem enriched with inline product details returned by the wishlist GET endpoint. */
31
34
  export interface EnrichedWishlistItem extends WishlistItem {
package/dist/index.d.ts CHANGED
@@ -913,6 +913,8 @@ export type { AboutHowItem } from "./features/about/index";
913
913
  export type { AboutMilestone } from "./features/about/index";
914
914
  export type { AboutValueItem } from "./features/about/index";
915
915
  export type { AboutViewProps } from "./features/about/index";
916
+ export type { AboutTeamMember } from "./features/about/index";
917
+ export type { AboutContentDocument } from "./features/about/index";
916
918
  export type { FAQPageViewProps } from "./features/about/index";
917
919
  export type { FeesViewProps } from "./features/about/index";
918
920
  export type { HelpPageViewProps } from "./features/about/index";
@@ -1149,6 +1151,10 @@ export { AdminNotificationsView } from "./features/admin/index";
1149
1151
  export { AdminCartsView } from "./features/admin/index";
1150
1152
  export { AdminWishlistsView } from "./features/admin/index";
1151
1153
  export { AdminHistoryView } from "./features/admin/index";
1154
+ export { AdminGroupedListingsView } from "./features/admin/index";
1155
+ export type { AdminGroupedListingsViewProps } from "./features/admin/index";
1156
+ export { AdminCarouselGroupEditorView } from "./features/admin/index";
1157
+ export type { AdminCarouselGroupEditorViewProps } from "./features/admin/index";
1152
1158
  export { AdminContactEditorView } from "./features/admin/index";
1153
1159
  export type { AdminContactEditorViewProps } from "./features/admin/index";
1154
1160
  export { AdminReturnRequestsView } from "./features/admin/index";
@@ -1180,6 +1186,10 @@ export { DEFAULT_TRUST_BAR_ITEMS } from "./features/admin/index";
1180
1186
  export { DashboardStatsGrid } from "./features/admin/index";
1181
1187
  export { AdminTeamView } from "./features/admin/index";
1182
1188
  export { AdminEmployeeEditorView } from "./features/admin/index";
1189
+ export { PERMISSION_GROUPS } from "./features/auth/permissions/constants";
1190
+ export { PERMISSION_DOMAINS } from "./features/auth/permissions/constants";
1191
+ export { getPermissionsForDomain } from "./features/auth/permissions/constants";
1192
+ export { formatPermLabel } from "./features/auth/permissions/constants";
1183
1193
  export { AdminSupportTicketsView } from "./features/admin/index";
1184
1194
  export { AdminSupportTicketDetailView } from "./features/admin/index";
1185
1195
  export { DrawerFormFooter } from "./features/admin/index";
@@ -2206,7 +2216,6 @@ export type { MediaUploadResult } from "./features/media/index";
2206
2216
  export type { MediaVideoProps } from "./features/media/index";
2207
2217
  export type { VideoThumbnailSelectorProps } from "./features/media/index";
2208
2218
  export type { VideoTrimModalProps } from "./features/media/index";
2209
- export { extractStoragePathFromUrl } from "./features/media/server";
2210
2219
  export { finalizeStagedMediaArray } from "./features/media/server";
2211
2220
  export { finalizeStagedMediaField } from "./features/media/server";
2212
2221
  export { finalizeStagedMediaObject } from "./features/media/server";
@@ -3088,7 +3097,7 @@ export { SUCCESS_MESSAGES } from "./values/index";
3088
3097
  export { splitCartIntoOrderGroups } from "./features/orders/index";
3089
3098
  export { groupOrderItemsByBundle, type BundleOrderGroup, type OrderItemForBundleGrouping, } from "./features/orders/index";
3090
3099
  export { buildSieveFilters } from "./utils/filter.helper";
3091
- export { formatFileSize } from "./utils/number.formatter";
3100
+ export { formatCurrency, formatFileSize } from "./utils/number.formatter";
3092
3101
  export { formatMonthYear } from "./utils/date.formatter";
3093
3102
  export { generateMediaFilename } from "./utils/id-generators";
3094
3103
  export { deriveContextTypeFromFilename } from "./utils/id-generators";
@@ -3217,8 +3226,6 @@ export { MarketplaceBundleCard } from "./features/products/index";
3217
3226
  export type { MarketplaceBundleCardProps, MarketplaceBundleCardData, MarketplaceBundleCardLabels, } from "./features/products/index";
3218
3227
  export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
3219
3228
  export type { SellerStoreCategoriesViewProps } from "./features/seller/components/SellerStoreCategoriesView";
3220
- export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
3221
- export type { SellerTemplatesViewProps } from "./features/seller/components/SellerTemplatesView";
3222
3229
  export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
3223
3230
  export type { SellerPayoutMethodsViewProps } from "./features/seller/components/SellerPayoutMethodsView";
3224
3231
  export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
package/dist/index.js CHANGED
@@ -1790,10 +1790,10 @@ export { createRazorpayRefund } from "./providers/payment-razorpay/index";
1790
1790
  // fetchRazorpayOrder - Shared export for fetch razorpay order.
1791
1791
  export { fetchRazorpayOrder } from "./providers/payment-razorpay/index";
1792
1792
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1793
- // paiseToRupees - Shared export for paise to rupees.
1793
+ // paiseToRupees - Shared export for paise to rupees. // audit-money-units-ok: names the boundary conversion function itself
1794
1794
  export { paiseToRupees } from "./providers/payment-razorpay/index";
1795
1795
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1796
- // rupeesToPaise - Shared export for rupees to paise.
1796
+ // rupeesToPaise - Shared export for rupees to paise. // audit-money-units-ok: names the boundary conversion function itself
1797
1797
  export { rupeesToPaise } from "./providers/payment-razorpay/index";
1798
1798
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1799
1799
  // verifyPaymentSignature - Shared export for verify payment signature.
@@ -2219,6 +2219,10 @@ export { AdminCartsView } from "./features/admin/index";
2219
2219
  export { AdminWishlistsView } from "./features/admin/index";
2220
2220
  // AdminHistoryView - Admin read-only history insights listing (S44 follow-up).
2221
2221
  export { AdminHistoryView } from "./features/admin/index";
2222
+ // AdminGroupedListingsView - Admin cross-store grouped-listings moderation view (W1-29).
2223
+ export { AdminGroupedListingsView } from "./features/admin/index";
2224
+ // AdminCarouselGroupEditorView - Create form for named carousel groups (EX2 nav-wiring fix).
2225
+ export { AdminCarouselGroupEditorView } from "./features/admin/index";
2222
2226
  // AdminContactEditorView - Admin contact submission detail SideDrawer (B7/VA15).
2223
2227
  export { AdminContactEditorView } from "./features/admin/index";
2224
2228
  // AdminReturnRequestsView - Admin return requests queue filtered to RETURN_REQUESTED (LL16).
@@ -2279,6 +2283,14 @@ export { DashboardStatsGrid } from "./features/admin/index";
2279
2283
  export { AdminTeamView } from "./features/admin/index";
2280
2284
  // AdminEmployeeEditorView - Invite/edit employee permissions SideDrawer.
2281
2285
  export { AdminEmployeeEditorView } from "./features/admin/index";
2286
+ // PERMISSION_GROUPS - Preset employee-group -> Permission[] bundles (S-ADMIN-7).
2287
+ export { PERMISSION_GROUPS } from "./features/auth/permissions/constants";
2288
+ // PERMISSION_DOMAINS - Domain label/prefix groupings for the permissions catalog page.
2289
+ export { PERMISSION_DOMAINS } from "./features/auth/permissions/constants";
2290
+ // getPermissionsForDomain - Every distinct permission across PERMISSION_GROUPS matching a domain prefix.
2291
+ export { getPermissionsForDomain } from "./features/auth/permissions/constants";
2292
+ // formatPermLabel - "admin:orders:read" -> "Read" display formatting.
2293
+ export { formatPermLabel } from "./features/auth/permissions/constants";
2282
2294
  // AdminSupportTicketsView - Admin support ticket list view.
2283
2295
  export { AdminSupportTicketsView } from "./features/admin/index";
2284
2296
  // AdminSupportTicketDetailView - Admin support ticket detail/reply SideDrawer.
@@ -4066,9 +4078,6 @@ export { useMediaTrim } from "./features/media/index";
4066
4078
  export { useMediaUpload } from "./features/media/index";
4067
4079
  // ./features/media/server
4068
4080
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
4069
- // extractStoragePathFromUrl - Shared export for extract storage path from url.
4070
- export { extractStoragePathFromUrl } from "./features/media/server";
4071
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
4072
4081
  // finalizeStagedMediaArray - Shared export for finalize staged media array.
4073
4082
  export { finalizeStagedMediaArray } from "./features/media/server";
4074
4083
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
@@ -5517,7 +5526,7 @@ export { splitCartIntoOrderGroups } from "./features/orders/index";
5517
5526
  export { groupOrderItemsByBundle, } from "./features/orders/index";
5518
5527
  // -- Missing utils
5519
5528
  export { buildSieveFilters } from "./utils/filter.helper";
5520
- export { formatFileSize } from "./utils/number.formatter";
5529
+ export { formatCurrency, formatFileSize } from "./utils/number.formatter";
5521
5530
  export { formatMonthYear } from "./utils/date.formatter";
5522
5531
  export { generateMediaFilename } from "./utils/id-generators"; // generateProductImageFilename already exported from "./utils/id-generators";
5523
5532
  export { deriveContextTypeFromFilename } from "./utils/id-generators";
@@ -5646,7 +5655,6 @@ export { getLiveItemForDetail } from "./_internal/server/features/live/data";
5646
5655
  export { MarketplaceBundleCard } from "./features/products/index";
5647
5656
  // ── Wave 4 Seller management views ───────────────────────────────────────────
5648
5657
  export { SellerStoreCategoriesView } from "./features/seller/components/SellerStoreCategoriesView";
5649
- export { SellerTemplatesView } from "./features/seller/components/SellerTemplatesView";
5650
5658
  export { SellerPayoutMethodsView } from "./features/seller/components/SellerPayoutMethodsView";
5651
5659
  export { SellerShippingConfigsView } from "./features/seller/components/SellerShippingConfigsView";
5652
5660
  export { SellerGoogleReviewsView } from "./features/seller/components/SellerGoogleReviewsView";
@@ -18,8 +18,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  */
19
19
  import { Heading, Text } from "../../ui/components/Typography";
20
20
  import { TextLink } from "../../ui/components/TextLink";
21
+ import { SiteMark } from "../../ui/components/SiteMark";
21
22
  import { DEFAULT_ROUTE_MAP } from "../routing/route-map";
22
23
  import { Stack } from "@mohasinac/appkit";
23
24
  export function NotFoundView({ heading = "404 — Page not found", description = "The page you are looking for does not exist.", homeLabel = "Go home", homeHref = DEFAULT_ROUTE_MAP.HOME, }) {
24
- return (_jsxs(Stack, { justify: "center", className: "min-h-[60vh] text-center", padding: "x-xl", align: "center", children: [_jsx(Heading, { level: 1, variant: "primary", size: "7xl", className: "mb-2", weight: "bold", children: "404" }), _jsx(Heading, { level: 2, className: "mb-3", children: heading }), _jsx(Text, { variant: "secondary", className: "mb-8", children: description }), _jsx(TextLink, { href: homeHref, children: homeLabel })] }));
25
+ return (_jsxs(Stack, { justify: "center", className: "min-h-[60vh] text-center", padding: "x-xl", align: "center", children: [_jsx(SiteMark, { size: "xl" }), _jsx(Heading, { level: 1, variant: "primary", size: "7xl", className: "mb-2", weight: "bold", children: "404" }), _jsx(Heading, { level: 2, className: "mb-3", children: heading }), _jsx(Text, { variant: "secondary", className: "mb-8", children: description }), _jsx(TextLink, { href: homeHref, children: homeLabel })] }));
25
26
  }