@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
@@ -2,14 +2,14 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
4
  import { useApiMutation } from "@mohasinac/appkit/client";
5
- import React, { useEffect, useMemo } from "react";
6
- import { z } from "zod";
5
+ import React, { useEffect } from "react";
7
6
  import { useQuery } from "@tanstack/react-query";
8
7
  import { Alert, Button, Div, Grid, Heading, Input, Label, RichTextEditor, Row, Select, Stack, StackedViewShell, TagInput, Text, Textarea, Toggle, } from "../../../ui";
9
8
  import { FormShellContext, useFormShellState, applyZodIssues, FormErrorSummary } from "../../../ui/forms";
10
9
  import { apiClient } from "../../../http";
11
10
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
12
- import { StepForm } from "../../shell";
11
+ import { SectionForm, useSectionFormNav } from "../../shell";
12
+ import { eventDraftSchema } from "../schemas/event-form";
13
13
  import { ProductInlineSelect } from "../../seller/components/ProductInlineSelect";
14
14
  import { CouponInlineSelect } from "../../seller/components/CouponInlineSelect";
15
15
  // Covers the cross-type required fields plus the two conditional rules the
@@ -19,27 +19,6 @@ import { CouponInlineSelect } from "../../seller/components/CouponInlineSelect";
19
19
  // form-builder arrays, raffle/spin config) are deliberately left unvalidated
20
20
  // — modeling their full conditional shape correctly would need much deeper
21
21
  // per-type domain rules than this pass is scoped for.
22
- const eventDraftSchema = z.object({
23
- type: z.string(),
24
- title: z.string().min(1, "Title is required"),
25
- startsAt: z.string().min(1, "Start date is required"),
26
- endsAt: z.string().min(1, "End date is required"),
27
- couponId: z.string(),
28
- displayCode: z.string(),
29
- pollOptions: z.array(z.object({ id: z.string(), label: z.string() })),
30
- }).passthrough().superRefine((v, ctx) => {
31
- if (v.type === "offer") {
32
- if (!v.couponId.trim()) {
33
- ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["couponId"], message: "Coupon is required for offer events" });
34
- }
35
- if (!v.displayCode.trim()) {
36
- ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["displayCode"], message: "Display code is required for offer events" });
37
- }
38
- }
39
- if (v.type === "poll" && v.pollOptions.filter((o) => o.label.trim()).length < 2) {
40
- ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["pollOptions"], message: "Poll events require at least 2 options" });
41
- }
42
- });
43
22
  const __P = {
44
23
  p4: "p-[var(--appkit-space-4)]",
45
24
  };
@@ -226,7 +205,6 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, allowedTypes,
226
205
  const isEdit = Boolean(eventId);
227
206
  const [draft, setDraft] = React.useState(DEFAULT_DRAFT);
228
207
  const [slugManual, setSlugManual] = React.useState(false);
229
- const [currentStep, setCurrentStep] = React.useState(0);
230
208
  const [saveMessage, setSaveMessage] = React.useState(null);
231
209
  const [triggerMessage, setTriggerMessage] = React.useState(null);
232
210
  const [raffleWinnerName, setRaffleWinnerName] = React.useState("");
@@ -358,44 +336,49 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, allowedTypes,
358
336
  });
359
337
  const isLoading = saveMutation.isPending || eventQuery.isLoading;
360
338
  // --- steps ---
361
- const steps = [
339
+ /**
340
+ * Sections, not steps — every field reachable at once, one submit at the
341
+ * bottom. The old wizard gated Settings behind Details validating, so a
342
+ * missing end date made an event's poll options unreachable.
343
+ *
344
+ * Ids match the schema's `section` annotations exactly, which is what lets
345
+ * `<FormErrorSummary>` jump to the right panel.
346
+ */
347
+ const sections = [
362
348
  {
349
+ id: "details",
350
+ required: true,
351
+ quick: true,
363
352
  label: "Details",
364
353
  fields: ["type", "title", "slug", "description", "startsAt", "endsAt", "tags"],
365
- validate: (values) => {
366
- if (!values.title.trim())
367
- return "Title is required";
368
- if (!values.startsAt)
369
- return "Start date is required";
370
- if (!values.endsAt)
371
- return "End date is required";
372
- return null;
373
- },
354
+ // The per-step `validate` is gone: every rule it stated is already in
355
+ // eventDraftSchema (title/startsAt/endsAt are .min(1)), and it only ever
356
+ // acted as a gate to the next step.
374
357
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Details" }), !isEdit && (_jsx(Select, { label: "Event type", value: values.type, options: allowedTypes ? EVENT_TYPE_OPTIONS.filter((o) => allowedTypes.includes(o.value)) : EVENT_TYPE_OPTIONS, onChange: (e) => onChange({ type: e.target.value }) })), _jsx(Input, { label: "Title", value: values.title, onChange: (e) => {
375
358
  const v = e.target.value;
376
359
  onChange({ title: v, ...(!slugManual && { slug: toEventSlug(v) }) });
377
360
  }, placeholder: "Charizard Flash Sale 2026", required: true }), _jsx(Input, { label: "Slug", value: values.slug, onChange: (e) => { setSlugManual(true); onChange({ slug: e.target.value }); }, placeholder: "event-charizard-flash-sale-2026", helperText: "Auto-generated from title. Must start with 'event-'." }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { children: "Description" }), _jsx(RichTextEditor, { value: values.description, onChange: (v) => onChange({ description: v }), minHeightClassName: "min-h-[120px]", placeholder: "Describe this event\u2026" })] }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Starts at", type: "datetime-local", value: values.startsAt, onChange: (e) => onChange({ startsAt: e.target.value }), required: true }), _jsx(Input, { label: "Ends at", type: "datetime-local", value: values.endsAt, onChange: (e) => onChange({ endsAt: e.target.value }), required: true })] }), _jsx(TagInput, { label: "Tags", value: values.tags, onChange: (t) => onChange({ tags: t }), placeholder: "e.g. pokemon, sale, 2026" })] })),
378
361
  },
379
362
  {
363
+ id: "media",
380
364
  label: "Media",
365
+ // <Collapse> unmounts its children — without this, collapsing the
366
+ // section mid-upload discards the transfer.
367
+ keepMounted: true,
381
368
  fields: ["coverImageUrl"],
382
369
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Media" }), _jsx(Input, { label: "Cover Image URL (optional)", value: values.coverImageUrl, onChange: (e) => onChange({ coverImageUrl: e.target.value }), placeholder: "https://\u2026", helperText: "Direct link to the event cover image." })] })),
383
370
  },
384
371
  {
372
+ id: "settings",
385
373
  label: "Settings",
386
374
  fields: ["status", "allowGuestParticipation", "discountPercent", "saleBannerText", "couponId", "displayCode", "offerBannerText", "pollOptions", "resultsVisibility", "allowMultiSelect", "allowComment", "maxEntriesPerUser", "hasLeaderboard", "hasPointSystem", "pointsLabel", "entryReviewRequired", "surveyFields", "anonymous", "feedbackFields"],
387
- validate: (values) => {
388
- if (values.type === "offer" && !values.couponId.trim())
389
- return "Coupon ID is required for offer events";
390
- if (values.type === "offer" && !values.displayCode.trim())
391
- return "Display code is required for offer events";
392
- if (values.type === "poll" && values.pollOptions.filter((o) => o.label.trim()).length < 2)
393
- return "Poll events require at least 2 options";
394
- return null;
395
- },
375
+ // Same: the offer-coupon, offer-display-code and poll-minimum-options
376
+ // rules are all stated in eventDraftSchema's superRefine, which now
377
+ // surfaces them inline on the field instead of as a step-blocking banner.
396
378
  render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Event Settings" }), isEdit && (_jsx(Select, { label: "Status", value: values.status, options: EVENT_STATUS_OPTIONS, onChange: (e) => onChange({ status: e.target.value }) })), values.createdBy && (_jsxs(Stack, { gap: "none", children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Created by" }), _jsx(Text, { size: "sm", color: "muted", children: values.createdBy })] })), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Toggle, { checked: values.allowGuestParticipation, onChange: (v) => onChange({ allowGuestParticipation: v }), label: "Allow guest participation (no login required)" }), _jsx(Text, { size: "xs", color: "muted", children: "When enabled, unauthenticated visitors can participate in this event (poll vote, survey/feedback response, raffle entry, or wheel spin), identified by a hashed IP address instead of an account. Applies uniformly to whatever entry mechanism this event type uses." })] }), values.type === "sale" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Sale configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Discount %", type: "number", value: values.discountPercent, onChange: (e) => onChange({ discountPercent: e.target.value }), placeholder: "10" }), _jsx(Input, { label: "Banner text (optional)", value: values.saleBannerText, onChange: (e) => onChange({ saleBannerText: e.target.value }), placeholder: "Limited time \u2014 ends Sunday!" })] })] })), values.type === "offer" && (_jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Offer configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "medium", className: "mb-1", children: "Coupon" }), _jsx(CouponInlineSelect, { scope: "admin", value: values.couponId, onChange: (id) => onChange({ couponId: id ?? "" }), placeholder: "Search coupons\u2026", allowCreate: false })] }), _jsx(Input, { label: "Display code", value: values.displayCode, onChange: (e) => onChange({ displayCode: e.target.value }), placeholder: "CHARIZARD25", required: true })] }), _jsx(Input, { label: "Banner text (optional)", value: values.offerBannerText, onChange: (e) => onChange({ offerBannerText: e.target.value }), placeholder: "Use CHARIZARD25 at checkout" })] })), values.type === "poll" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Poll configuration" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "xs", color: "muted", children: "Options (minimum 2)" }), values.pollOptions.map((opt, idx) => (_jsxs(Row, { gap: "xs", children: [_jsx(Div, { className: "flex-1", children: _jsx(Input, { value: opt.label, onChange: (e) => onChange({ pollOptions: values.pollOptions.map((o) => o.id === opt.id ? { ...o, label: e.target.value } : o) }), placeholder: `Option ${idx + 1}` }) }), values.pollOptions.length > 2 && (_jsx(Button, { variant: "ghost", type: "button", onClick: () => onChange({ pollOptions: values.pollOptions.filter((o) => o.id !== opt.id) }), className: CLS_REMOVE_BTN_PX2, "aria-label": "Remove option", children: "\u00D7" }))] }, opt.id))), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange({ pollOptions: [...values.pollOptions, { id: `opt${Date.now()}`, label: "" }] }), children: "+ Add option" })] }), _jsx(Select, { label: "Results visibility", value: values.resultsVisibility, options: POLL_VISIBILITY_OPTIONS, onChange: (e) => onChange({ resultsVisibility: e.target.value }) }), _jsxs(Stack, { gap: "sm", children: [_jsx(Toggle, { checked: values.allowMultiSelect, onChange: (v) => onChange({ allowMultiSelect: v }), label: "Allow multi-select" }), _jsx(Toggle, { checked: values.allowComment, onChange: (v) => onChange({ allowComment: v }), label: "Allow comment with vote" })] })] })), values.type === "survey" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Survey configuration" }), _jsxs(Grid, { cols: 2, gap: "sm", children: [_jsx(Input, { label: "Max entries per user", type: "number", value: values.maxEntriesPerUser, onChange: (e) => onChange({ maxEntriesPerUser: e.target.value }), placeholder: "1" }), values.hasPointSystem && (_jsx(Input, { label: "Points label", value: values.pointsLabel, onChange: (e) => onChange({ pointsLabel: e.target.value }), placeholder: "Points" }))] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Toggle, { checked: values.requireLogin, onChange: (v) => onChange({ requireLogin: v }), label: "Require login to participate" }), _jsx(Toggle, { checked: values.hasLeaderboard, onChange: (v) => onChange({ hasLeaderboard: v }), label: "Show leaderboard" }), _jsx(Toggle, { checked: values.hasPointSystem, onChange: (v) => onChange({ hasPointSystem: v }), label: "Enable point system" }), _jsx(Toggle, { checked: values.entryReviewRequired, onChange: (v) => onChange({ entryReviewRequired: v }), label: "Require employee review before entry is approved" })] }), _jsx(FormFieldBuilder, { fields: values.surveyFields, setFields: (f) => onChange({ surveyFields: f }) })] })), values.type === "feedback" && (_jsxs(Stack, { gap: "md", rounded: "xl", border: "default", padding: "md", children: [_jsx(Text, { size: "sm", weight: "semibold", color: "muted", children: "Feedback configuration" }), _jsx(Toggle, { checked: values.anonymous, onChange: (v) => onChange({ anonymous: v }), label: "Allow anonymous submissions" }), _jsx(FormFieldBuilder, { fields: values.feedbackFields, setFields: (f) => onChange({ feedbackFields: f }) })] }))] })),
397
379
  },
398
380
  {
381
+ id: "raffle",
399
382
  label: "Raffle / Spin",
400
383
  fields: ["hasRaffle", "raffleType", "raffleTopN", "rafflePrize", "rafflePrizeCouponId", "rafflePrizeProductIds", "spinPrizes", "spinMaxPerUser", "spinWindowStart", "spinWindowEnd"],
401
384
  render: ({ values, onChange }) => {
@@ -407,16 +390,11 @@ export function AdminEventEditorView({ eventId, onSaved, embedded, allowedTypes,
407
390
  },
408
391
  ];
409
392
  const alertSection = eventQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load event", children: eventQuery.error instanceof Error ? eventQuery.error.message : "Unknown error" })) : null;
410
- const fieldToStepIndex = useMemo(() => {
411
- const map = {};
412
- steps.forEach((step, i) => {
413
- step.fields?.forEach((field) => { map[field] = i; });
414
- });
415
- return map;
416
- // eslint-disable-next-line react-hooks/exhaustive-deps
417
- }, [steps.length]);
418
- const wizardShellCtx = useMemo(() => ({ ...shellCtx, fieldToStepIndex, goToStep: (n) => setCurrentStep(n) }), [shellCtx, fieldToStepIndex, setCurrentStep]);
419
- const formContent = (_jsxs(Stack, { gap: "sm", children: [alertSection, _jsxs(FormShellContext.Provider, { value: wizardShellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(StepForm, { steps: steps, values: draft, onChange: update, onComplete: () => { saveMutation.mutate(); }, formId: "admin-event", currentStep: currentStep, onStepChange: setCurrentStep, completeLabel: isEdit ? "Save Changes" : "Create Event", isLoading: isLoading })] }), saveMessage && (_jsx(Alert, { variant: saveMessage.toLowerCase().includes("fail") || saveMessage.toLowerCase().includes("error") ? "error" : "success", title: "Save status", children: saveMessage }))] }));
393
+ // Replaces the hand-rolled fieldToStepIndex + goToStep pair. The hook owns
394
+ // the expand-then-scroll ordering a raw setState cannot: a collapsed panel
395
+ // must MOUNT before scrollIntoView and focus can reach the offending field.
396
+ const { openIds, setOpenIds, goToSection, fieldToSectionIndex, sectionMeta } = useSectionFormNav(sections, draft);
397
+ const formContent = (_jsxs(Stack, { gap: "sm", children: [alertSection, _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: draft, onChange: update, onSubmit: () => { saveMutation.mutate(); }, schema: eventDraftSchema, openIds: openIds, onOpenChange: setOpenIds, submitLabel: isEdit ? "Save Changes" : "Create Event", isLoading: isLoading })] }), saveMessage && (_jsx(Alert, { variant: saveMessage.toLowerCase().includes("fail") || saveMessage.toLowerCase().includes("error") ? "error" : "success", title: "Save status", children: saveMessage }))] }));
420
398
  if (embedded) {
421
399
  return _jsx(Div, { className: `${__O.yAuto} ${__P.p4}`, children: formContent });
422
400
  }
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useApiMutation, sieveFilter, SIEVE_OP, sortBy } from "@mohasinac/appkit/client";
4
- import React from "react";
4
+ import React, { useState } from "react";
5
5
  import { useQuery, useQueryClient } from "@tanstack/react-query";
6
- import { Alert, Button, Div, Input, Row, Select, Stack, Text, useToast } from "../../../ui";
6
+ import { Alert, Button, Div, Input, Row, Select, Stack, Text, useToast, RecordDetailModal, } from "../../../ui";
7
7
  import { apiClient } from "../../../http";
8
8
  import { normalizeError } from "../../../errors/normalize";
9
9
  import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
@@ -128,6 +128,10 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
128
128
  },
129
129
  ];
130
130
  const eventTitle = statsQuery.data?.event?.title;
131
+ // Approve / Waitlist / Cancel were offered on an entry the admin could never
132
+ // read — the poll vote, the comment and the survey answers were all invisible
133
+ // (Root Cause #56, "acting blind"). The row already carries the whole entry.
134
+ const [detail, setDetail] = useState(null);
131
135
  const config = {
132
136
  portal: "admin",
133
137
  title: eventTitle ? `${eventTitle} Entries` : "Event Entries",
@@ -139,6 +143,7 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
139
143
  endpoint: resolvedEntriesEndpoint,
140
144
  sortOptions: [{ value: sortBy("submittedAt", "DESC"), label: "Most recent" }],
141
145
  columns,
146
+ onRowClick: (row) => setDetail(row),
142
147
  mapRows: (response) => response.items ?? [],
143
148
  getTotal: (response) => response.total ?? (response.items ?? []).length,
144
149
  buildFilters: (state) => state.reviewStatus ? sieveFilter("reviewStatus", SIEVE_OP.EQ, state.reviewStatus) : undefined,
@@ -146,5 +151,19 @@ export function AdminEventEntriesView({ eventId, entriesEndpoint, entryReviewEnd
146
151
  toolbarExtra: eventId ? (_jsx(Button, { variant: "ghost", action: ACTIONS.ADMIN["export-event-entries"], onClick: handleExportReport })) : undefined,
147
152
  renderAboveContent: () => (_jsxs(Stack, { gap: "3", className: "px-[var(--appkit-space-3)] pb-[var(--appkit-space-2)]", children: [!eventId ? (_jsx(Alert, { variant: "warning", title: "Missing event id", children: "Event id is required to load entries." })) : null, statsQuery.error ? (_jsx(Alert, { variant: "error", title: "Could not load event stats", children: statsQuery.error instanceof Error ? statsQuery.error.message : "Unknown error" })) : null, _jsxs(Div, { layout: "grid", gap: "3", className: "grid-cols-1 sm:grid-cols-3", children: [_jsx(Alert, { variant: "info", title: "Total entries", children: String(statsQuery.data?.stats?.totalEntries ?? 0) }), _jsx(Alert, { variant: "success", title: "Approved", children: String(statsQuery.data?.stats?.approvedEntries ?? 0) }), _jsx(Alert, { variant: "warning", title: "Flagged", children: String(statsQuery.data?.stats?.flaggedEntries ?? 0) })] })] })),
148
153
  };
149
- return _jsx(DataListingView, { config: config });
154
+ return (_jsxs(_Fragment, { children: [_jsx(DataListingView, { config: config }), _jsx(RecordDetailModal, { isOpen: detail !== null, onClose: () => setDetail(null), title: detail?.userDisplayName || detail?.userEmail || "Entry", badges: detail ? [{ label: detail.reviewStatus }] : undefined, description: detail?.pollComment, fields: detail
155
+ ? [
156
+ { label: "Entrant", value: detail.userDisplayName ?? detail.userId ?? "—" },
157
+ { label: "Email", value: detail.userEmail ?? "—" },
158
+ { label: "Review status", value: detail.reviewStatus },
159
+ { label: "Points", value: detail.points != null ? String(detail.points) : "—" },
160
+ { label: "Raffle eligible", value: detail.raffleEligible ? "Yes" : "No" },
161
+ { label: "Poll votes", value: detail.pollVotes?.join(", ") || "—" },
162
+ { label: "Reviewed by", value: detail.reviewedBy ?? "—" },
163
+ { label: "Review note", value: detail.reviewNote ?? "—" },
164
+ { label: "Entry ID", value: detail.id },
165
+ ]
166
+ : undefined,
167
+ // The survey/feedback answers — the actual submission being judged.
168
+ metadata: detail?.formResponses })] }));
150
169
  }
@@ -0,0 +1,113 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * ## `.passthrough()` STAYS here, deliberately
4
+ *
5
+ * `EventDraft` carries ~40 fields; this schema names seven. The blog form's
6
+ * equivalent was safe to tighten because its draft had fourteen fields and all
7
+ * fourteen could be named in one sitting. This one cannot: most of its fields
8
+ * are per-event-type (poll options, survey fields, spin prizes, raffle config)
9
+ * and only apply under a `type` discriminator, so naming them correctly means
10
+ * modelling the discriminated union rather than listing keys.
11
+ *
12
+ * Tightening it blind is the single most dangerous edit available in this
13
+ * codebase — `z.object()` strips unknown keys, so every field this schema
14
+ * failed to name would vanish from the draft the moment passthrough came off.
15
+ * That is exactly how `productBaseSchema` came to eat every `classified*` /
16
+ * `digitalCode*` / `liveItem*` / `prize*` field.
17
+ *
18
+ * The wire payload is NOT at risk either way: it is built explicitly below
19
+ * (`type`, `title`, `slug`, … plus `buildEventTypeConfig` /
20
+ * `buildEventRaffleFields`), never by spreading the draft.
21
+ *
22
+ * Prerequisite for removing it: a FULL-collection `roundtrip-diff --entity
23
+ * event --full`, not a sample — per the data-integrity protocol.
24
+ *
25
+ * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
26
+ * by schema instance and every zod wrapper returns a new one.
27
+ */
28
+ export declare const eventDraftSchema: z.ZodEffects<z.ZodObject<{
29
+ type: z.ZodString;
30
+ title: z.ZodString;
31
+ startsAt: z.ZodString;
32
+ endsAt: z.ZodString;
33
+ couponId: z.ZodString;
34
+ displayCode: z.ZodString;
35
+ pollOptions: z.ZodArray<z.ZodObject<{
36
+ id: z.ZodString;
37
+ label: z.ZodString;
38
+ }, "strip", z.ZodTypeAny, {
39
+ id: string;
40
+ label: string;
41
+ }, {
42
+ id: string;
43
+ label: string;
44
+ }>, "many">;
45
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
46
+ type: z.ZodString;
47
+ title: z.ZodString;
48
+ startsAt: z.ZodString;
49
+ endsAt: z.ZodString;
50
+ couponId: z.ZodString;
51
+ displayCode: z.ZodString;
52
+ pollOptions: z.ZodArray<z.ZodObject<{
53
+ id: z.ZodString;
54
+ label: z.ZodString;
55
+ }, "strip", z.ZodTypeAny, {
56
+ id: string;
57
+ label: string;
58
+ }, {
59
+ id: string;
60
+ label: string;
61
+ }>, "many">;
62
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
63
+ type: z.ZodString;
64
+ title: z.ZodString;
65
+ startsAt: z.ZodString;
66
+ endsAt: z.ZodString;
67
+ couponId: z.ZodString;
68
+ displayCode: z.ZodString;
69
+ pollOptions: z.ZodArray<z.ZodObject<{
70
+ id: z.ZodString;
71
+ label: z.ZodString;
72
+ }, "strip", z.ZodTypeAny, {
73
+ id: string;
74
+ label: string;
75
+ }, {
76
+ id: string;
77
+ label: string;
78
+ }>, "many">;
79
+ }, z.ZodTypeAny, "passthrough">>, z.objectOutputType<{
80
+ type: z.ZodString;
81
+ title: z.ZodString;
82
+ startsAt: z.ZodString;
83
+ endsAt: z.ZodString;
84
+ couponId: z.ZodString;
85
+ displayCode: z.ZodString;
86
+ pollOptions: z.ZodArray<z.ZodObject<{
87
+ id: z.ZodString;
88
+ label: z.ZodString;
89
+ }, "strip", z.ZodTypeAny, {
90
+ id: string;
91
+ label: string;
92
+ }, {
93
+ id: string;
94
+ label: string;
95
+ }>, "many">;
96
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
97
+ type: z.ZodString;
98
+ title: z.ZodString;
99
+ startsAt: z.ZodString;
100
+ endsAt: z.ZodString;
101
+ couponId: z.ZodString;
102
+ displayCode: z.ZodString;
103
+ pollOptions: z.ZodArray<z.ZodObject<{
104
+ id: z.ZodString;
105
+ label: z.ZodString;
106
+ }, "strip", z.ZodTypeAny, {
107
+ id: string;
108
+ label: string;
109
+ }, {
110
+ id: string;
111
+ label: string;
112
+ }>, "many">;
113
+ }, z.ZodTypeAny, "passthrough">>;
@@ -0,0 +1,82 @@
1
+ /*
2
+ * WHY: Same reason as the blog form schema — keeping it in the `.tsx` view
3
+ * would have dragged a React component tree into every API route through
4
+ * `SCHEMAS` -> `routeHandler`.
5
+ * WHAT: The event editor's form schema, with its UI metadata.
6
+ *
7
+ * EXPORTS:
8
+ * eventDraftSchema
9
+ *
10
+ * @tag domain:events
11
+ * @tag layer:schema
12
+ * @tag pattern:none
13
+ * @tag access:isomorphic
14
+ * @tag consumers:AdminEventEditorView,SCHEMAS.forms
15
+ * @tag sideEffects:none
16
+ */
17
+ import { z } from "zod";
18
+ import { annotate } from "../../shell/field-ui-meta";
19
+ /**
20
+ * ## `.passthrough()` STAYS here, deliberately
21
+ *
22
+ * `EventDraft` carries ~40 fields; this schema names seven. The blog form's
23
+ * equivalent was safe to tighten because its draft had fourteen fields and all
24
+ * fourteen could be named in one sitting. This one cannot: most of its fields
25
+ * are per-event-type (poll options, survey fields, spin prizes, raffle config)
26
+ * and only apply under a `type` discriminator, so naming them correctly means
27
+ * modelling the discriminated union rather than listing keys.
28
+ *
29
+ * Tightening it blind is the single most dangerous edit available in this
30
+ * codebase — `z.object()` strips unknown keys, so every field this schema
31
+ * failed to name would vanish from the draft the moment passthrough came off.
32
+ * That is exactly how `productBaseSchema` came to eat every `classified*` /
33
+ * `digitalCode*` / `liveItem*` / `prize*` field.
34
+ *
35
+ * The wire payload is NOT at risk either way: it is built explicitly below
36
+ * (`type`, `title`, `slug`, … plus `buildEventTypeConfig` /
37
+ * `buildEventRaffleFields`), never by spreading the draft.
38
+ *
39
+ * Prerequisite for removing it: a FULL-collection `roundtrip-diff --entity
40
+ * event --full`, not a sample — per the data-integrity protocol.
41
+ *
42
+ * 🛑 `annotate()` must be the OUTERMOST call on each field — it keys a WeakMap
43
+ * by schema instance and every zod wrapper returns a new one.
44
+ */
45
+ export const eventDraftSchema = z.object({
46
+ type: annotate(z.string(), {
47
+ section: "details", sectionLabel: "Details", sectionRequired: true,
48
+ quick: true, order: 1, row: "pair", kind: "select",
49
+ }),
50
+ title: annotate(z.string().min(1, "Title is required"), {
51
+ section: "details", quick: true, order: 2, row: "full",
52
+ }),
53
+ startsAt: annotate(z.string().min(1, "Start date is required"), {
54
+ section: "details", quick: true, order: 3, row: "pair", kind: "date",
55
+ }),
56
+ endsAt: annotate(z.string().min(1, "End date is required"), {
57
+ section: "details", quick: true, order: 4, row: "pair", kind: "date",
58
+ }),
59
+ couponId: annotate(z.string(), {
60
+ section: "settings", sectionLabel: "Settings", order: 1, row: "pair",
61
+ help: "Required for offer events.",
62
+ }),
63
+ displayCode: annotate(z.string(), {
64
+ section: "settings", order: 2, row: "pair",
65
+ help: "Required for offer events.",
66
+ }),
67
+ pollOptions: annotate(z.array(z.object({ id: z.string(), label: z.string() })), {
68
+ section: "settings", order: 3, row: "full", kind: "list",
69
+ }),
70
+ }).passthrough().superRefine((v, ctx) => {
71
+ if (v.type === "offer") {
72
+ if (!v.couponId.trim()) {
73
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["couponId"], message: "Coupon is required for offer events" });
74
+ }
75
+ if (!v.displayCode.trim()) {
76
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["displayCode"], message: "Display code is required for offer events" });
77
+ }
78
+ }
79
+ if (v.type === "poll" && v.pollOptions.filter((o) => o.label.trim()).length < 2) {
80
+ ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["pollOptions"], message: "Poll events require at least 2 options" });
81
+ }
82
+ });
@@ -943,10 +943,10 @@ export declare const eventItemSchema: z.ZodObject<{
943
943
  title: string;
944
944
  createdAt: string;
945
945
  updatedAt: string;
946
+ createdBy: string;
946
947
  description: string;
947
948
  startsAt: string;
948
949
  endsAt: string;
949
- createdBy: string;
950
950
  stats: {
951
951
  totalEntries: number;
952
952
  approvedEntries: number;
@@ -1098,10 +1098,10 @@ export declare const eventItemSchema: z.ZodObject<{
1098
1098
  title: string;
1099
1099
  createdAt: string;
1100
1100
  updatedAt: string;
1101
+ createdBy: string;
1101
1102
  description: string;
1102
1103
  startsAt: string;
1103
1104
  endsAt: string;
1104
- createdBy: string;
1105
1105
  stats: {
1106
1106
  totalEntries: number;
1107
1107
  approvedEntries: number;
@@ -27,10 +27,10 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
27
27
  template: z.ZodOptional<z.ZodString>;
28
28
  }, "strip", z.ZodTypeAny, {
29
29
  category: string;
30
+ priority: number;
30
31
  isActive: boolean;
31
32
  order: number;
32
33
  showOnHomepage: boolean;
33
- priority: number;
34
34
  question: string;
35
35
  answer: {
36
36
  text: string;
@@ -51,11 +51,11 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
51
51
  format?: "html" | "plain" | "markdown" | undefined;
52
52
  };
53
53
  template?: string | undefined;
54
+ priority?: number | undefined;
54
55
  tags?: string[] | undefined;
55
56
  isActive?: boolean | undefined;
56
57
  order?: number | undefined;
57
58
  showOnHomepage?: boolean | undefined;
58
- priority?: number | undefined;
59
59
  showInFooter?: boolean | undefined;
60
60
  isPinned?: boolean | undefined;
61
61
  relatedFAQs?: string[] | undefined;
@@ -63,10 +63,10 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
63
63
  variables?: Record<string, string> | undefined;
64
64
  }>, {
65
65
  category: string;
66
+ priority: number;
66
67
  isActive: boolean;
67
68
  order: number;
68
69
  showOnHomepage: boolean;
69
- priority: number;
70
70
  question: string;
71
71
  answer: {
72
72
  text: string;
@@ -87,11 +87,11 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
87
87
  format?: "html" | "plain" | "markdown" | undefined;
88
88
  };
89
89
  template?: string | undefined;
90
+ priority?: number | undefined;
90
91
  tags?: string[] | undefined;
91
92
  isActive?: boolean | undefined;
92
93
  order?: number | undefined;
93
94
  showOnHomepage?: boolean | undefined;
94
- priority?: number | undefined;
95
95
  showInFooter?: boolean | undefined;
96
96
  isPinned?: boolean | undefined;
97
97
  relatedFAQs?: string[] | undefined;
@@ -125,11 +125,11 @@ export declare const faqUpdateSchema: z.ZodObject<{
125
125
  }, "strip", z.ZodTypeAny, {
126
126
  template?: string | undefined;
127
127
  category?: string | undefined;
128
+ priority?: number | undefined;
128
129
  tags?: string[] | undefined;
129
130
  isActive?: boolean | undefined;
130
131
  order?: number | undefined;
131
132
  showOnHomepage?: boolean | undefined;
132
- priority?: number | undefined;
133
133
  question?: string | undefined;
134
134
  answer?: {
135
135
  text: string;
@@ -143,11 +143,11 @@ export declare const faqUpdateSchema: z.ZodObject<{
143
143
  }, {
144
144
  template?: string | undefined;
145
145
  category?: string | undefined;
146
+ priority?: number | undefined;
146
147
  tags?: string[] | undefined;
147
148
  isActive?: boolean | undefined;
148
149
  order?: number | undefined;
149
150
  showOnHomepage?: boolean | undefined;
150
- priority?: number | undefined;
151
151
  question?: string | undefined;
152
152
  answer?: {
153
153
  text: string;
@@ -91,6 +91,7 @@ export declare const faqSchema: z.ZodObject<{
91
91
  };
92
92
  createdAt?: string | undefined;
93
93
  updatedAt?: string | undefined;
94
+ priority?: number | undefined;
94
95
  tags?: string[] | undefined;
95
96
  isActive?: boolean | undefined;
96
97
  order?: number | undefined;
@@ -100,7 +101,6 @@ export declare const faqSchema: z.ZodObject<{
100
101
  notHelpful?: number | undefined;
101
102
  } | undefined;
102
103
  showOnHomepage?: boolean | undefined;
103
- priority?: number | undefined;
104
104
  showInFooter?: boolean | undefined;
105
105
  isPinned?: boolean | undefined;
106
106
  relatedFAQs?: string[] | undefined;
@@ -117,6 +117,7 @@ export declare const faqSchema: z.ZodObject<{
117
117
  };
118
118
  createdAt?: string | undefined;
119
119
  updatedAt?: string | undefined;
120
+ priority?: number | undefined;
120
121
  tags?: string[] | undefined;
121
122
  isActive?: boolean | undefined;
122
123
  order?: number | undefined;
@@ -126,7 +127,6 @@ export declare const faqSchema: z.ZodObject<{
126
127
  notHelpful?: number | undefined;
127
128
  } | undefined;
128
129
  showOnHomepage?: boolean | undefined;
129
- priority?: number | undefined;
130
130
  showInFooter?: boolean | undefined;
131
131
  isPinned?: boolean | undefined;
132
132
  relatedFAQs?: string[] | undefined;
@@ -282,10 +282,11 @@ export declare const faqFirestoreSchema: z.ZodObject<{
282
282
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
283
283
  }, z.ZodTypeAny, "passthrough">;
284
284
  category: "orders_payment" | "shipping_delivery" | "returns_refunds" | "product_information" | "account_security" | "technical_support" | "general";
285
+ createdBy: string;
286
+ priority: number;
285
287
  tags: string[];
286
288
  isActive: boolean;
287
289
  order: number;
288
- createdBy: string;
289
290
  stats: {
290
291
  views: number;
291
292
  helpful: number;
@@ -295,7 +296,6 @@ export declare const faqFirestoreSchema: z.ZodObject<{
295
296
  }, z.ZodTypeAny, "passthrough"> | undefined;
296
297
  };
297
298
  showOnHomepage: boolean;
298
- priority: number;
299
299
  question: string;
300
300
  answer: {
301
301
  text: string;
@@ -321,10 +321,11 @@ export declare const faqFirestoreSchema: z.ZodObject<{
321
321
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
322
322
  }, z.ZodTypeAny, "passthrough">;
323
323
  category: "orders_payment" | "shipping_delivery" | "returns_refunds" | "product_information" | "account_security" | "technical_support" | "general";
324
+ createdBy: string;
325
+ priority: number;
324
326
  tags: string[];
325
327
  isActive: boolean;
326
328
  order: number;
327
- createdBy: string;
328
329
  stats: {
329
330
  views: number;
330
331
  helpful: number;
@@ -334,7 +335,6 @@ export declare const faqFirestoreSchema: z.ZodObject<{
334
335
  }, z.ZodTypeAny, "passthrough"> | undefined;
335
336
  };
336
337
  showOnHomepage: boolean;
337
- priority: number;
338
338
  question: string;
339
339
  answer: {
340
340
  text: string;