@mohasinac/appkit 4.14.0 → 4.16.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 (206) hide show
  1. package/dist/_internal/server/features/auctions/actions.js +2 -2
  2. package/dist/_internal/server/features/cart/service.d.ts +3 -3
  3. package/dist/_internal/server/features/checkout/actions.js +19 -0
  4. package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
  5. package/dist/_internal/server/features/checkout/source-context.js +157 -0
  6. package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
  7. package/dist/_internal/server/features/offers/adapters.js +88 -0
  8. package/dist/_internal/server/features/offers/index.d.ts +2 -0
  9. package/dist/_internal/server/features/offers/index.js +1 -0
  10. package/dist/_internal/server/features/orders/adapters.js +24 -0
  11. package/dist/_internal/server/jobs/core/offerExpiry.js +10 -10
  12. package/dist/_internal/shared/actions/action-registry.d.ts +9 -2
  13. package/dist/_internal/shared/actions/action-registry.js +458 -7
  14. package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
  15. package/dist/_internal/shared/features/auctions/schema.js +13 -1
  16. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  17. package/dist/_internal/shared/features/cart/schema.d.ts +25 -20
  18. package/dist/_internal/shared/features/cart/schema.js +15 -0
  19. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +22 -22
  20. package/dist/_internal/shared/features/orders/schema.d.ts +4 -4
  21. package/dist/_internal/shared/features/products/schema.d.ts +27 -27
  22. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  23. package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
  24. package/dist/_internal/shared/history/history.d.ts +22 -0
  25. package/dist/_internal/shared/history/history.js +41 -1
  26. package/dist/client.d.ts +13 -2
  27. package/dist/client.js +20 -2
  28. package/dist/constants/field-names.d.ts +8 -6
  29. package/dist/constants/field-names.js +48 -6
  30. package/dist/contracts/extend.d.ts +29 -0
  31. package/dist/contracts/extend.js +20 -0
  32. package/dist/contracts/index.d.ts +2 -1
  33. package/dist/contracts/index.js +2 -0
  34. package/dist/features/account/components/UserBidsView.js +12 -4
  35. package/dist/features/account/components/UserReturnsView.d.ts +3 -0
  36. package/dist/features/account/components/UserReturnsView.js +17 -1
  37. package/dist/features/admin/components/AdminAuditLogView.js +1 -0
  38. package/dist/features/admin/components/AdminBidsView.js +15 -2
  39. package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
  40. package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
  41. package/dist/features/admin/components/AdminNavEditorView.js +15 -5
  42. package/dist/features/admin/components/AdminNewsletterView.js +18 -2
  43. package/dist/features/admin/components/AdminOffersView.js +62 -18
  44. package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
  45. package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
  46. package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
  47. package/dist/features/admin/components/AdminScammersView.js +3 -8
  48. package/dist/features/admin/components/AdminSectionsView.js +32 -23
  49. package/dist/features/admin/components/AdminSessionsView.js +17 -2
  50. package/dist/features/admin/components/AdminViewCards.js +24 -17
  51. package/dist/features/admin/components/DataListingView.js +15 -1
  52. package/dist/features/admin/components/DataTable.js +7 -17
  53. package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
  54. package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -2
  55. package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
  56. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  57. package/dist/features/admin/constants/filter-tabs.js +1 -0
  58. package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
  59. package/dist/features/admin/schemas/homepage-section-form.js +68 -0
  60. package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
  61. package/dist/features/admin/schemas/nav-item-form.js +72 -0
  62. package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
  63. package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
  64. package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
  65. package/dist/features/auctions/components/bid-detail-fields.js +103 -0
  66. package/dist/features/auctions/schemas/index.d.ts +14 -14
  67. package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
  68. package/dist/features/audit-log/schemas/firestore.js +7 -0
  69. package/dist/features/auth/schemas/index.d.ts +2 -2
  70. package/dist/features/blog/actions/blog-actions.d.ts +7 -7
  71. package/dist/features/blog/schemas/blog-form.d.ts +80 -0
  72. package/dist/features/blog/schemas/blog-form.js +100 -0
  73. package/dist/features/blog/schemas/index.d.ts +10 -10
  74. package/dist/features/cart/schemas/index.d.ts +3 -3
  75. package/dist/features/catalogue/schemas/validation.d.ts +12 -12
  76. package/dist/features/categories/schemas/index.d.ts +16 -16
  77. package/dist/features/collections/schemas/index.d.ts +8 -8
  78. package/dist/features/events/components/AdminEventEditorView.js +32 -54
  79. package/dist/features/events/components/AdminEventEntriesView.js +22 -3
  80. package/dist/features/events/schemas/event-form.d.ts +113 -0
  81. package/dist/features/events/schemas/event-form.js +82 -0
  82. package/dist/features/events/schemas/index.d.ts +2 -2
  83. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  84. package/dist/features/faq/schemas/index.d.ts +6 -6
  85. package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
  86. package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
  87. package/dist/features/grouped/schemas/index.d.ts +4 -4
  88. package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
  89. package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
  90. package/dist/features/homepage/schemas/index.d.ts +71 -40
  91. package/dist/features/homepage/schemas/index.js +24 -0
  92. package/dist/features/messages/schemas/index.d.ts +2 -2
  93. package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
  94. package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
  95. package/dist/features/orders/repository/orders.repository.js +5 -0
  96. package/dist/features/orders/schemas/firestore.d.ts +36 -1
  97. package/dist/features/orders/schemas/index.d.ts +24 -24
  98. package/dist/features/orders/types/index.d.ts +35 -7
  99. package/dist/features/pre-orders/schemas/index.d.ts +4 -4
  100. package/dist/features/products/components/GroupSettingsPanel.js +5 -1
  101. package/dist/features/products/schemas/index.d.ts +38 -38
  102. package/dist/features/products/schemas/product-features.validators.d.ts +75 -2
  103. package/dist/features/products/schemas/product-features.validators.js +63 -0
  104. package/dist/features/promotions/schemas/index.d.ts +14 -14
  105. package/dist/features/reviews/schemas/index.d.ts +14 -14
  106. package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
  107. package/dist/features/scams/constants/scammer-status-display.js +79 -0
  108. package/dist/features/scams/schemas/index.d.ts +2 -2
  109. package/dist/features/search/schemas/index.d.ts +2 -2
  110. package/dist/features/seller/actions/offer-actions.js +32 -2
  111. package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
  112. package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
  113. package/dist/features/seller/components/SellerBidsView.js +11 -4
  114. package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
  115. package/dist/features/seller/components/SellerOffersView.js +2 -1
  116. package/dist/features/seller/components/SellerPayoutSettingsView.js +38 -14
  117. package/dist/features/seller/repository/offer.repository.d.ts +69 -8
  118. package/dist/features/seller/repository/offer.repository.js +127 -23
  119. package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
  120. package/dist/features/seller/schemas/coupon-form.js +116 -0
  121. package/dist/features/seller/schemas/firestore.d.ts +56 -2
  122. package/dist/features/seller/schemas/firestore.js +27 -0
  123. package/dist/features/seller/schemas/index.d.ts +2 -2
  124. package/dist/features/seller/schemas/offer-forms.d.ts +21 -0
  125. package/dist/features/seller/schemas/offer-forms.js +21 -0
  126. package/dist/features/shell/build-sections.d.ts +63 -0
  127. package/dist/features/shell/build-sections.js +207 -0
  128. package/dist/features/shell/field-ui-meta.d.ts +115 -0
  129. package/dist/features/shell/field-ui-meta.js +324 -0
  130. package/dist/features/shell/index.d.ts +4 -0
  131. package/dist/features/shell/index.js +2 -0
  132. package/dist/features/shipments/schemas/validation.d.ts +22 -22
  133. package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
  134. package/dist/features/status-history/components/StatusTimeline.js +46 -0
  135. package/dist/features/status-history/index.d.ts +11 -0
  136. package/dist/features/status-history/index.js +10 -0
  137. package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
  138. package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
  139. package/dist/features/store-extensions/index.d.ts +12 -0
  140. package/dist/features/store-extensions/index.js +12 -0
  141. package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
  142. package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
  143. package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
  144. package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
  145. package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
  146. package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
  147. package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
  148. package/dist/features/store-extensions/schemas/firestore.js +60 -0
  149. package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
  150. package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
  151. package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
  152. package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
  153. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
  154. package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
  155. package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
  156. package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
  157. package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
  158. package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
  159. package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
  160. package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
  161. package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
  162. package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
  163. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
  164. package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
  165. package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
  166. package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
  167. package/dist/features/stores/schemas/index.d.ts +4 -4
  168. package/dist/features/support/schemas/index.d.ts +4 -4
  169. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +350 -0
  170. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  171. package/dist/index.d.ts +12 -2
  172. package/dist/index.js +12 -2
  173. package/dist/next/routing/route-map.d.ts +16 -2
  174. package/dist/next/routing/route-map.js +9 -2
  175. package/dist/schemas/firestore-value.d.ts +8 -0
  176. package/dist/schemas/firestore-value.js +44 -0
  177. package/dist/schemas/index.d.ts +1 -1
  178. package/dist/schemas/index.js +1 -1
  179. package/dist/schemas/registry.d.ts +734 -101
  180. package/dist/schemas/registry.js +64 -1
  181. package/dist/seed/bids-seed-data.js +30 -0
  182. package/dist/seed/offers-seed-data.js +212 -7
  183. package/dist/seed/orders-seed-data.js +336 -1
  184. package/dist/seed/products-auctions-seed-data.js +41 -0
  185. package/dist/server.d.ts +2 -0
  186. package/dist/server.js +5 -0
  187. package/dist/styles.css +1 -1
  188. package/dist/tailwind-utilities.css +1 -1
  189. package/dist/ui/DataTable.js +4 -2
  190. package/dist/ui/columns/build-columns.d.ts +6 -1
  191. package/dist/ui/columns/build-columns.js +53 -0
  192. package/dist/ui/columns/cell-renderers.d.ts +68 -0
  193. package/dist/ui/columns/cell-renderers.js +111 -0
  194. package/dist/ui/columns/column-renderers.d.ts +6 -1
  195. package/dist/ui/columns/column-renderers.js +6 -1
  196. package/dist/ui/columns/index.d.ts +2 -1
  197. package/dist/ui/columns/index.js +5 -1
  198. package/dist/ui/components/Button.js +27 -2
  199. package/dist/ui/components/RecordDetailModal.d.ts +10 -1
  200. package/dist/ui/components/RecordDetailModal.js +2 -2
  201. package/dist/ui/icons/icon-registry.d.ts +65 -0
  202. package/dist/ui/icons/icon-registry.js +115 -0
  203. package/package.json +2 -1
  204. package/scripts/node-esm-loader.mjs +65 -0
  205. package/scripts/seed-cli-loader.mjs +6 -49
  206. package/scripts/seed-cli.mjs +1 -1
@@ -0,0 +1,101 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
4
+ * by schema instance and every zod wrapper returns a new one.
5
+ */
6
+ export declare const groupedListingFormSchema: z.ZodObject<{
7
+ title: z.ZodString;
8
+ description: z.ZodOptional<z.ZodString>;
9
+ groupTheme: z.ZodEnum<["related", "character", "lineage", "set", "generic"]>;
10
+ productIds: z.ZodArray<z.ZodString, "many">;
11
+ minActiveMembers: z.ZodNumber;
12
+ coverImage: z.ZodOptional<z.ZodString>;
13
+ isActive: z.ZodBoolean;
14
+ isFeatured: z.ZodBoolean;
15
+ }, "strip", z.ZodTypeAny, {
16
+ title: string;
17
+ isActive: boolean;
18
+ isFeatured: boolean;
19
+ productIds: string[];
20
+ groupTheme: "set" | "related" | "character" | "lineage" | "generic";
21
+ minActiveMembers: number;
22
+ description?: string | undefined;
23
+ coverImage?: string | undefined;
24
+ }, {
25
+ title: string;
26
+ isActive: boolean;
27
+ isFeatured: boolean;
28
+ productIds: string[];
29
+ groupTheme: "set" | "related" | "character" | "lineage" | "generic";
30
+ minActiveMembers: number;
31
+ description?: string | undefined;
32
+ coverImage?: string | undefined;
33
+ }>;
34
+ export type GroupedListingFormValues = z.infer<typeof groupedListingFormSchema>;
35
+ /**
36
+ * Create contract. `storeId` is absent — the store route sets it from the
37
+ * session, so a seller cannot file a group under another store.
38
+ */
39
+ export declare const groupedListingCreateSchema: z.ZodObject<{
40
+ title: z.ZodString;
41
+ description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
42
+ isActive: z.ZodBoolean;
43
+ isFeatured: z.ZodOptional<z.ZodBoolean>;
44
+ coverImage: z.ZodOptional<z.ZodOptional<z.ZodString>>;
45
+ productIds: z.ZodArray<z.ZodString, "many">;
46
+ groupTheme: z.ZodEnum<["related", "character", "lineage", "set", "generic"]>;
47
+ minActiveMembers: z.ZodOptional<z.ZodNumber>;
48
+ }, "strip", z.ZodTypeAny, {
49
+ title: string;
50
+ isActive: boolean;
51
+ productIds: string[];
52
+ groupTheme: "set" | "related" | "character" | "lineage" | "generic";
53
+ description?: string | undefined;
54
+ isFeatured?: boolean | undefined;
55
+ coverImage?: string | undefined;
56
+ minActiveMembers?: number | undefined;
57
+ }, {
58
+ title: string;
59
+ isActive: boolean;
60
+ productIds: string[];
61
+ groupTheme: "set" | "related" | "character" | "lineage" | "generic";
62
+ description?: string | undefined;
63
+ isFeatured?: boolean | undefined;
64
+ coverImage?: string | undefined;
65
+ minActiveMembers?: number | undefined;
66
+ }>;
67
+ /** Update contract — partial, `.strict()` so an unknown key is a 400. */
68
+ export declare const groupedListingUpdateSchema: z.ZodObject<{
69
+ title: z.ZodOptional<z.ZodString>;
70
+ description: z.ZodOptional<z.ZodString>;
71
+ groupTheme: z.ZodOptional<z.ZodEnum<["related", "character", "lineage", "set", "generic"]>>;
72
+ productIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
73
+ minActiveMembers: z.ZodOptional<z.ZodNumber>;
74
+ coverImage: z.ZodOptional<z.ZodString>;
75
+ isActive: z.ZodOptional<z.ZodBoolean>;
76
+ isFeatured: z.ZodOptional<z.ZodBoolean>;
77
+ brandSlug: z.ZodOptional<z.ZodString>;
78
+ categorySlug: z.ZodOptional<z.ZodString>;
79
+ }, "strict", z.ZodTypeAny, {
80
+ title?: string | undefined;
81
+ categorySlug?: string | undefined;
82
+ brandSlug?: string | undefined;
83
+ description?: string | undefined;
84
+ isActive?: boolean | undefined;
85
+ isFeatured?: boolean | undefined;
86
+ coverImage?: string | undefined;
87
+ productIds?: string[] | undefined;
88
+ groupTheme?: "set" | "related" | "character" | "lineage" | "generic" | undefined;
89
+ minActiveMembers?: number | undefined;
90
+ }, {
91
+ title?: string | undefined;
92
+ categorySlug?: string | undefined;
93
+ brandSlug?: string | undefined;
94
+ description?: string | undefined;
95
+ isActive?: boolean | undefined;
96
+ isFeatured?: boolean | undefined;
97
+ coverImage?: string | undefined;
98
+ productIds?: string[] | undefined;
99
+ groupTheme?: "set" | "related" | "character" | "lineage" | "generic" | undefined;
100
+ minActiveMembers?: number | undefined;
101
+ }>;
@@ -0,0 +1,89 @@
1
+ /*
2
+ * WHY: `POST /api/store/grouped-listings` spread the raw request body into
3
+ * `.create()` and its PATCH built `{...body}` — no Zod on either. The two
4
+ * pages behind them validated one field between them (`new` checked
5
+ * `title` was non-empty and toasted; `[id]/edit` checked nothing at all).
6
+ * WHAT: One schema for the pages AND the store routes.
7
+ *
8
+ * ## `activeMemberCount` is NOT in this schema
9
+ *
10
+ * It is derived — both routes already recompute it from `productIds.length`,
11
+ * which is correct and was verified rather than assumed. Accepting it from the
12
+ * body would let a caller set a count that disagrees with the array, and the
13
+ * count is what the public visibility check reads.
14
+ *
15
+ * `slug`, `visibilityStatus` and `createdBy` are absent for the same reason:
16
+ * derived or session-owned, never typed.
17
+ *
18
+ * EXPORTS:
19
+ * groupedListingFormSchema, groupedListingCreateSchema,
20
+ * groupedListingUpdateSchema, type GroupedListingFormValues
21
+ *
22
+ * @tag domain:grouped
23
+ * @tag layer:schema
24
+ * @tag pattern:none
25
+ * @tag access:isomorphic
26
+ * @tag consumers:store/grouped-listings pages,/api/store/grouped-listings
27
+ * @tag sideEffects:none
28
+ */
29
+ import { z } from "zod";
30
+ import { annotate } from "../../shell/field-ui-meta";
31
+ /** Mirrors `GroupTheme` in ./firestore. */
32
+ const groupThemeSchema = z.enum(["related", "character", "lineage", "set", "generic"]);
33
+ /**
34
+ * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
35
+ * by schema instance and every zod wrapper returns a new one.
36
+ */
37
+ export const groupedListingFormSchema = z.object({
38
+ title: annotate(z.string().min(1, "Title is required").max(120, "Keep the title under 120 characters."), {
39
+ section: "basics", sectionLabel: "Group", sectionRequired: true,
40
+ quick: true, order: 1, row: "full",
41
+ }),
42
+ description: annotate(z.string().max(500, "Keep the description under 500 characters.").optional(), {
43
+ section: "basics", order: 2, row: "full",
44
+ }),
45
+ groupTheme: annotate(groupThemeSchema, {
46
+ section: "basics", quick: true, order: 3, row: "pair",
47
+ }),
48
+ productIds: annotate(z.array(z.string()), {
49
+ section: "members", sectionLabel: "Members", order: 1, row: "full", kind: "list",
50
+ }),
51
+ minActiveMembers: annotate(z.coerce.number().int("Must be a whole number.").min(1, "A group needs at least one member to show."), {
52
+ section: "members", order: 2, row: "pair",
53
+ help: "Below this many in-stock members, the group hides itself.",
54
+ }),
55
+ coverImage: annotate(z.string().optional(), {
56
+ section: "media", sectionLabel: "Media", order: 1, row: "full", kind: "media",
57
+ }),
58
+ isActive: annotate(z.boolean(), {
59
+ section: "visibility", sectionLabel: "Visibility", order: 1, row: "quarter",
60
+ }),
61
+ isFeatured: annotate(z.boolean(), {
62
+ section: "visibility", order: 2, row: "quarter",
63
+ }),
64
+ });
65
+ /**
66
+ * Create contract. `storeId` is absent — the store route sets it from the
67
+ * session, so a seller cannot file a group under another store.
68
+ */
69
+ export const groupedListingCreateSchema = groupedListingFormSchema.partial({
70
+ description: true,
71
+ coverImage: true,
72
+ isFeatured: true,
73
+ minActiveMembers: true,
74
+ });
75
+ /** Update contract — partial, `.strict()` so an unknown key is a 400. */
76
+ export const groupedListingUpdateSchema = z
77
+ .object({
78
+ title: z.string().min(1).max(120).optional(),
79
+ description: z.string().max(500).optional(),
80
+ groupTheme: groupThemeSchema.optional(),
81
+ productIds: z.array(z.string()).optional(),
82
+ minActiveMembers: z.coerce.number().int().min(1).optional(),
83
+ coverImage: z.string().optional(),
84
+ isActive: z.boolean().optional(),
85
+ isFeatured: z.boolean().optional(),
86
+ brandSlug: z.string().optional(),
87
+ categorySlug: z.string().optional(),
88
+ })
89
+ .strict();
@@ -43,8 +43,8 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
43
43
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
44
44
  }, z.ZodTypeAny, "passthrough">;
45
45
  slug: string;
46
- isActive: boolean;
47
46
  createdBy: string;
47
+ isActive: boolean;
48
48
  isFeatured: boolean;
49
49
  productIds: string[];
50
50
  groupTheme: "set" | "related" | "character" | "lineage" | "generic";
@@ -52,9 +52,9 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
52
52
  minActiveMembers: number;
53
53
  activeMemberCount: number;
54
54
  storeId?: string | undefined;
55
- description?: string | undefined;
56
55
  categorySlug?: string | undefined;
57
56
  brandSlug?: string | undefined;
57
+ description?: string | undefined;
58
58
  coverImage?: string | undefined;
59
59
  }, {
60
60
  id: string;
@@ -66,8 +66,8 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
66
66
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
67
67
  }, z.ZodTypeAny, "passthrough">;
68
68
  slug: string;
69
- isActive: boolean;
70
69
  createdBy: string;
70
+ isActive: boolean;
71
71
  isFeatured: boolean;
72
72
  productIds: string[];
73
73
  groupTheme: "set" | "related" | "character" | "lineage" | "generic";
@@ -75,9 +75,9 @@ export declare const groupedListingFirestoreSchema: z.ZodObject<{
75
75
  minActiveMembers: number;
76
76
  activeMemberCount: number;
77
77
  storeId?: string | undefined;
78
- description?: string | undefined;
79
78
  categorySlug?: string | undefined;
80
79
  brandSlug?: string | undefined;
80
+ description?: string | undefined;
81
81
  coverImage?: string | undefined;
82
82
  }>;
83
83
  export type GroupedListingFromSchema = z.infer<typeof groupedListingFirestoreSchema>;
@@ -2,21 +2,29 @@ import { z } from "zod";
2
2
  import type { HomepageSectionDocument } from "../schemas";
3
3
  import type { FirebaseSieveResult } from "../../../providers/db-firebase";
4
4
  export declare const createSectionSchema: z.ZodObject<{
5
- type: z.ZodString;
5
+ type: z.ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
6
6
  enabled: z.ZodDefault<z.ZodBoolean>;
7
7
  order: z.ZodDefault<z.ZodNumber>;
8
8
  config: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, z.objectOutputType<{}, z.ZodTypeAny, "passthrough">, z.objectInputType<{}, z.ZodTypeAny, "passthrough">>>;
9
9
  }, "strip", z.ZodTypeAny, {
10
- type: string;
10
+ type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
11
11
  enabled: boolean;
12
12
  order: number;
13
13
  config?: z.objectOutputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
14
14
  }, {
15
- type: string;
15
+ type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
16
16
  enabled?: boolean | undefined;
17
17
  order?: number | undefined;
18
18
  config?: z.objectInputType<{}, z.ZodTypeAny, "passthrough"> | undefined;
19
19
  }>;
20
+ /**
21
+ * The next free `order` value.
22
+ *
23
+ * `HomepageSectionCreateInput.order` is REQUIRED, and both API create routes
24
+ * need the same answer for "the caller did not choose one". Two copies of this
25
+ * query is how they would come to disagree about where a new section lands.
26
+ */
27
+ export declare function resolveNextSectionOrder(): Promise<number>;
20
28
  export declare const updateSectionSchema: z.ZodObject<{
21
29
  order: z.ZodOptional<z.ZodNumber>;
22
30
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -1,13 +1,45 @@
1
1
  import { z } from "zod";
2
2
  import { serverLogger } from "../../../monitoring";
3
+ import { sortBy } from "../../../constants/sort";
4
+ import { HOMEPAGE_SECTION_FIELDS } from "../../../constants/field-names";
3
5
  import { homepageSectionsRepository } from "../repository/homepage-sections.repository";
6
+ import { homepageSectionTypeSchema } from "../schemas";
4
7
  // --- Schemas --------------------------------------------------------------
8
+ /*
9
+ * 🛑 `type` was `z.string().min(1)` — ANY non-empty string.
10
+ *
11
+ * This is the third of three create paths for `homepageSections`
12
+ * (`POST /api/admin/sections`, `POST /api/homepage-sections`, and this server
13
+ * action via `createHomepageSectionAction`), and it was the loosest: a caller
14
+ * could store a section whose `type` matches no renderer, which the homepage
15
+ * then skips in silence — a row that exists, occupies an order slot, and draws
16
+ * nothing.
17
+ *
18
+ * All three now agree on `homepageSectionTypeSchema`, which is derived from
19
+ * the `SectionType` union.
20
+ */
5
21
  export const createSectionSchema = z.object({
6
- type: z.string().min(1),
22
+ type: homepageSectionTypeSchema,
7
23
  enabled: z.boolean().default(true),
8
24
  order: z.number().int().default(0),
9
25
  config: z.object({}).passthrough().optional(),
10
26
  });
27
+ /**
28
+ * The next free `order` value.
29
+ *
30
+ * `HomepageSectionCreateInput.order` is REQUIRED, and both API create routes
31
+ * need the same answer for "the caller did not choose one". Two copies of this
32
+ * query is how they would come to disagree about where a new section lands.
33
+ */
34
+ export async function resolveNextSectionOrder() {
35
+ const latest = await homepageSectionsRepository.list({
36
+ sorts: sortBy(HOMEPAGE_SECTION_FIELDS.ORDER),
37
+ page: "1",
38
+ pageSize: "1",
39
+ });
40
+ const top = latest.items[0]?.order;
41
+ return typeof top === "number" ? top + 1 : 1;
42
+ }
11
43
  export const updateSectionSchema = z.object({
12
44
  order: z.number().int().optional(),
13
45
  enabled: z.boolean().optional(),
@@ -47,6 +47,37 @@ export declare const homepageSectionFirestoreSchema: z.ZodObject<{
47
47
  order: number;
48
48
  config: Record<string, JsonValue>;
49
49
  }>;
50
+ /**
51
+ * The create contract for a homepage section, shared by BOTH routes that can
52
+ * create one — `POST /api/admin/sections` (what the editor calls) and
53
+ * `POST /api/homepage-sections` (reachable by URL only).
54
+ *
55
+ * It exists because those two had drifted into being one validated path and
56
+ * one raw `{...body}` spread, and because the validated one's hand-written
57
+ * type list had fallen four values behind `SectionType` — so an admin could
58
+ * configure a Featured Bundles / Prize Draws / Event Raffles / Collection
59
+ * Cards section in full and get a 400 on save.
60
+ *
61
+ * `type` comes from `homepageSectionTypeSchema`, which is derived from the
62
+ * union, so that gap cannot reopen.
63
+ */
64
+ export declare const homepageSectionCreateSchema: z.ZodObject<{
65
+ type: z.ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
66
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
67
+ order: z.ZodOptional<z.ZodNumber>;
68
+ config: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, z.ZodTypeDef, JsonValue>>;
69
+ }, "strip", z.ZodTypeAny, {
70
+ type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
71
+ enabled: boolean;
72
+ config: Record<string, JsonValue>;
73
+ order?: number | undefined;
74
+ }, {
75
+ type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
76
+ config: Record<string, JsonValue>;
77
+ enabled?: boolean | undefined;
78
+ order?: number | undefined;
79
+ }>;
80
+ export type HomepageSectionCreateValues = z.infer<typeof homepageSectionCreateSchema>;
50
81
  export declare const carouselBackgroundSchema: z.ZodObject<{
51
82
  type: z.ZodEnum<["image", "video", "color", "gradient"]>;
52
83
  url: z.ZodOptional<z.ZodString>;
@@ -660,8 +691,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
660
691
  id?: string | undefined;
661
692
  } | undefined;
662
693
  enabled?: boolean | undefined;
663
- opacity?: number | undefined;
664
694
  description?: string | undefined;
695
+ opacity?: number | undefined;
665
696
  subtitle?: string | undefined;
666
697
  }, {
667
698
  color?: string | undefined;
@@ -674,8 +705,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
674
705
  id?: string | undefined;
675
706
  } | undefined;
676
707
  enabled?: boolean | undefined;
677
- opacity?: number | undefined;
678
708
  description?: string | undefined;
709
+ opacity?: number | undefined;
679
710
  subtitle?: string | undefined;
680
711
  }>>;
681
712
  settings: z.ZodOptional<z.ZodObject<{
@@ -718,9 +749,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
718
749
  updatedAt: string | Date | z.objectOutputType<{
719
750
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
720
751
  }, z.ZodTypeAny, "passthrough">;
721
- active: boolean;
722
- order: number;
723
752
  createdBy: string;
753
+ active: boolean;
724
754
  cards: {
725
755
  id: string;
726
756
  background: {
@@ -763,10 +793,22 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
763
793
  isButtonOnly?: boolean | undefined;
764
794
  gridCol?: 3 | 1 | 2 | undefined;
765
795
  }[];
796
+ order: number;
766
797
  link?: {
767
798
  url: string;
768
799
  openInNewTab: boolean;
769
800
  } | undefined;
801
+ media?: {
802
+ type: "video" | "image";
803
+ url: string;
804
+ alt?: string | undefined;
805
+ thumbnail?: string | undefined;
806
+ } | undefined;
807
+ mobileMedia?: {
808
+ type: "video" | "image";
809
+ url: string;
810
+ alt?: string | undefined;
811
+ } | undefined;
770
812
  background?: {
771
813
  type: "color" | "gradient" | "video" | "image";
772
814
  color?: string | undefined;
@@ -792,32 +834,21 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
792
834
  id?: string | undefined;
793
835
  } | undefined;
794
836
  enabled?: boolean | undefined;
795
- opacity?: number | undefined;
796
837
  description?: string | undefined;
838
+ opacity?: number | undefined;
797
839
  subtitle?: string | undefined;
798
840
  } | undefined;
799
- media?: {
800
- type: "video" | "image";
801
- url: string;
802
- alt?: string | undefined;
803
- thumbnail?: string | undefined;
804
- } | undefined;
805
- mobileMedia?: {
806
- type: "video" | "image";
807
- url: string;
808
- alt?: string | undefined;
809
- } | undefined;
810
- settings?: {
811
- height?: "medium" | "viewport" | "tall" | undefined;
812
- autoplayDelayMs?: number | undefined;
813
- } | undefined;
814
- carouselId?: string | null | undefined;
815
841
  analytics?: {
816
842
  views: number;
817
843
  lastViewed?: string | Date | z.objectOutputType<{
818
844
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
819
845
  }, z.ZodTypeAny, "passthrough"> | undefined;
820
846
  } | undefined;
847
+ settings?: {
848
+ height?: "medium" | "viewport" | "tall" | undefined;
849
+ autoplayDelayMs?: number | undefined;
850
+ } | undefined;
851
+ carouselId?: string | null | undefined;
821
852
  }, {
822
853
  id: string;
823
854
  title: string;
@@ -827,9 +858,8 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
827
858
  updatedAt: string | Date | z.objectInputType<{
828
859
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
829
860
  }, z.ZodTypeAny, "passthrough">;
830
- active: boolean;
831
- order: number;
832
861
  createdBy: string;
862
+ active: boolean;
833
863
  cards: {
834
864
  id: string;
835
865
  background: {
@@ -872,10 +902,22 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
872
902
  isButtonOnly?: boolean | undefined;
873
903
  gridCol?: 3 | 1 | 2 | undefined;
874
904
  }[];
905
+ order: number;
875
906
  link?: {
876
907
  url: string;
877
908
  openInNewTab: boolean;
878
909
  } | undefined;
910
+ media?: {
911
+ type: "video" | "image";
912
+ url: string;
913
+ alt?: string | undefined;
914
+ thumbnail?: string | undefined;
915
+ } | undefined;
916
+ mobileMedia?: {
917
+ type: "video" | "image";
918
+ url: string;
919
+ alt?: string | undefined;
920
+ } | undefined;
879
921
  background?: {
880
922
  type: "color" | "gradient" | "video" | "image";
881
923
  color?: string | undefined;
@@ -901,32 +943,21 @@ export declare const carouselSlideFirestoreSchema: z.ZodObject<{
901
943
  id?: string | undefined;
902
944
  } | undefined;
903
945
  enabled?: boolean | undefined;
904
- opacity?: number | undefined;
905
946
  description?: string | undefined;
947
+ opacity?: number | undefined;
906
948
  subtitle?: string | undefined;
907
949
  } | undefined;
908
- media?: {
909
- type: "video" | "image";
910
- url: string;
911
- alt?: string | undefined;
912
- thumbnail?: string | undefined;
913
- } | undefined;
914
- mobileMedia?: {
915
- type: "video" | "image";
916
- url: string;
917
- alt?: string | undefined;
918
- } | undefined;
919
- settings?: {
920
- height?: "medium" | "viewport" | "tall" | undefined;
921
- autoplayDelayMs?: number | undefined;
922
- } | undefined;
923
- carouselId?: string | null | undefined;
924
950
  analytics?: {
925
951
  views: number;
926
952
  lastViewed?: string | Date | z.objectInputType<{
927
953
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
928
954
  }, z.ZodTypeAny, "passthrough"> | undefined;
929
955
  } | undefined;
956
+ settings?: {
957
+ height?: "medium" | "viewport" | "tall" | undefined;
958
+ autoplayDelayMs?: number | undefined;
959
+ } | undefined;
960
+ carouselId?: string | null | undefined;
930
961
  }>;
931
962
  export type HomepageSectionFromSchema = z.infer<typeof homepageSectionFirestoreSchema>;
932
963
  export type CarouselFromSchema = z.infer<typeof carouselFirestoreSchema>;
@@ -56,6 +56,30 @@ export const homepageSectionFirestoreSchema = z.object({
56
56
  config: z.record(z.string(), jsonValueSchema),
57
57
  ...auditTimestampsShape,
58
58
  });
59
+ /**
60
+ * The create contract for a homepage section, shared by BOTH routes that can
61
+ * create one — `POST /api/admin/sections` (what the editor calls) and
62
+ * `POST /api/homepage-sections` (reachable by URL only).
63
+ *
64
+ * It exists because those two had drifted into being one validated path and
65
+ * one raw `{...body}` spread, and because the validated one's hand-written
66
+ * type list had fallen four values behind `SectionType` — so an admin could
67
+ * configure a Featured Bundles / Prize Draws / Event Raffles / Collection
68
+ * Cards section in full and get a 400 on save.
69
+ *
70
+ * `type` comes from `homepageSectionTypeSchema`, which is derived from the
71
+ * union, so that gap cannot reopen.
72
+ */
73
+ export const homepageSectionCreateSchema = z.object({
74
+ type: homepageSectionTypeSchema,
75
+ enabled: z.boolean().optional().default(true),
76
+ order: z.number().int().optional(),
77
+ // Deliberately open. Every section type carries a different config shape,
78
+ // and a closed schema here would silently STRIP the builder's output for any
79
+ // type it did not enumerate — the `productBaseSchema` failure, one domain
80
+ // over.
81
+ config: z.record(z.string(), jsonValueSchema),
82
+ });
59
83
  export const carouselBackgroundSchema = z.object({
60
84
  type: z.enum(["image", "video", "color", "gradient"]),
61
85
  url: z.string().optional(),
@@ -116,8 +116,8 @@ export declare const conversationFirestoreSchema: z.ZodObject<{
116
116
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
117
117
  }, z.ZodTypeAny, "passthrough">;
118
118
  storeId: string;
119
- buyerId: string;
120
119
  storeName: string;
120
+ buyerId: string;
121
121
  lastMessageAt: string | Date | z.objectOutputType<{
122
122
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
123
123
  }, z.ZodTypeAny, "passthrough">;
@@ -149,8 +149,8 @@ export declare const conversationFirestoreSchema: z.ZodObject<{
149
149
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
150
150
  }, z.ZodTypeAny, "passthrough">;
151
151
  storeId: string;
152
- buyerId: string;
153
152
  storeName: string;
153
+ buyerId: string;
154
154
  lastMessageAt: string | Date | z.objectInputType<{
155
155
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
156
156
  }, z.ZodTypeAny, "passthrough">;
@@ -1,5 +1,9 @@
1
+ import { type TimelineEntry } from "../../status-history/components/StatusTimeline";
1
2
  export interface OrderStatusTimelineProps {
2
3
  orderStatus: string;
4
+ /** Recorded history. When present it wins over the scalar-date fallback. */
5
+ timeline?: TimelineEntry[];
6
+ timelineTruncated?: number;
3
7
  orderDate?: string;
4
8
  shippingDate?: string;
5
9
  deliveryDate?: string;
@@ -9,4 +13,4 @@ export interface OrderStatusTimelineProps {
9
13
  trackingUrl?: string;
10
14
  className?: string;
11
15
  }
12
- export declare function OrderStatusTimeline({ orderStatus, orderDate, shippingDate, deliveryDate, cancellationDate, trackingNumber, shippingCarrier, trackingUrl, className, }: OrderStatusTimelineProps): import("react").JSX.Element;
16
+ export declare function OrderStatusTimeline({ orderStatus, timeline, timelineTruncated, orderDate, shippingDate, deliveryDate, cancellationDate, trackingNumber, shippingCarrier, trackingUrl, className, }: OrderStatusTimelineProps): import("react").JSX.Element;