@mohasinac/appkit 4.62.1 → 4.63.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 (261) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +51 -11
  8. package/dist/_internal/server/features/checkout/actions.js +335 -80
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  22. package/dist/_internal/server/features/offers/destinations.js +65 -0
  23. package/dist/_internal/server/features/orders/adapters.js +21 -0
  24. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  25. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  26. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  27. package/dist/_internal/server/features/orders/balance.js +256 -0
  28. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  29. package/dist/_internal/server/features/pricing/actions.js +144 -0
  30. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  31. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  32. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  33. package/dist/_internal/server/features/shipping/book.js +176 -0
  34. package/dist/_internal/server/features/shipping/courier-block.js +26 -1
  35. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  36. package/dist/_internal/server/features/site-settings/adapters.js +14 -0
  37. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  38. package/dist/_internal/server/features/stores/adapters.js +14 -0
  39. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  40. package/dist/_internal/server/functions/scheduled.js +57 -1
  41. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +2 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  43. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +4 -1
  44. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  45. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  46. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -0
  47. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  48. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  49. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  50. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  51. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  52. package/dist/_internal/shared/actions/action-registry.js +268 -0
  53. package/dist/_internal/shared/checkout/order-math.d.ts +31 -2
  54. package/dist/_internal/shared/checkout/order-math.js +22 -36
  55. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  56. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  57. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  58. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  59. package/dist/_internal/shared/checkout/split.d.ts +0 -12
  60. package/dist/_internal/shared/checkout/split.js +22 -2
  61. package/dist/_internal/shared/content/disclaimers.js +7 -7
  62. package/dist/_internal/shared/content/published-values.d.ts +6 -1
  63. package/dist/_internal/shared/content/published-values.js +8 -0
  64. package/dist/_internal/shared/features/admin/integrations.d.ts +32 -2
  65. package/dist/_internal/shared/features/admin/integrations.js +19 -9
  66. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  67. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  68. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  69. package/dist/_internal/shared/features/emi/choice.js +69 -0
  70. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  71. package/dist/_internal/shared/features/emi/group.js +126 -0
  72. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  73. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  74. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  75. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  76. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  77. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  78. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  79. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  80. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  81. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  82. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  83. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  84. package/dist/_internal/shared/features/points/accepts.d.ts +1 -8
  85. package/dist/_internal/shared/features/points/accepts.js +12 -6
  86. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  87. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  88. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  89. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  90. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  91. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  92. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  93. package/dist/_internal/shared/fees/explain.js +101 -0
  94. package/dist/_internal/shared/history/index.d.ts +1 -1
  95. package/dist/_internal/shared/history/index.js +1 -1
  96. package/dist/_internal/shared/history/types.d.ts +7 -1
  97. package/dist/_internal/shared/history/types.js +25 -0
  98. package/dist/client.d.ts +11 -1
  99. package/dist/client.js +13 -0
  100. package/dist/constants/api-endpoints.d.ts +72 -0
  101. package/dist/constants/api-endpoints.js +41 -0
  102. package/dist/constants/field-names.d.ts +41 -0
  103. package/dist/constants/field-names.js +47 -0
  104. package/dist/features/account/components/UserOrdersView.js +28 -2
  105. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  106. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  107. package/dist/features/admin/components/AdminOrderEditorView.d.ts +16 -1
  108. package/dist/features/admin/components/AdminOrderEditorView.js +72 -3
  109. package/dist/features/admin/components/AdminOrdersView.js +20 -1
  110. package/dist/features/admin/schemas/firestore.d.ts +32 -0
  111. package/dist/features/ads/schemas/booking-write.d.ts +120 -0
  112. package/dist/features/ads/schemas/booking-write.js +75 -0
  113. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  114. package/dist/features/ads/schemas/creative-form.js +51 -0
  115. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  116. package/dist/features/ads/schemas/firestore.js +109 -0
  117. package/dist/features/auctions/repository/bid.repository.js +3 -1
  118. package/dist/features/audit-log/schemas/firestore.d.ts +110 -0
  119. package/dist/features/audit-log/schemas/firestore.js +74 -0
  120. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  121. package/dist/features/auth/actions/profile-actions.js +62 -1
  122. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  123. package/dist/features/auth/schemas/firestore.js +2 -1
  124. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  125. package/dist/features/blog/actions/blog-actions.js +17 -2
  126. package/dist/features/blog/api/route.js +4 -1
  127. package/dist/features/blog/columns/index.js +5 -0
  128. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  129. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  130. package/dist/features/blog/repository/blog.repository.js +5 -0
  131. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  132. package/dist/features/blog/schemas/blog-form.js +1 -0
  133. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  134. package/dist/features/blog/schemas/firestore.js +23 -0
  135. package/dist/features/blog/schemas/index.d.ts +6 -0
  136. package/dist/features/blog/schemas/index.js +2 -0
  137. package/dist/features/blog/types/index.d.ts +2 -0
  138. package/dist/features/cart/components/CartPriceBreakdown.d.ts +12 -1
  139. package/dist/features/cart/components/CartPriceBreakdown.js +24 -5
  140. package/dist/features/cart/repository/cart.repository.d.ts +14 -0
  141. package/dist/features/cart/repository/cart.repository.js +20 -0
  142. package/dist/features/cart/schemas/firestore.d.ts +24 -0
  143. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  144. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  145. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  146. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  147. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  148. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  149. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +24 -0
  150. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +28 -0
  151. package/dist/features/dispute-reasons/schemas/firestore.d.ts +3 -5
  152. package/dist/features/events/components/EventSaleBanner.js +1 -1
  153. package/dist/features/faq/components/FAQPageContent.js +2 -2
  154. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  155. package/dist/features/homepage/schemas/index.d.ts +8 -8
  156. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  157. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  158. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  159. package/dist/features/layout/AppLayoutShell.js +12 -4
  160. package/dist/features/layout/BottomActions.js +2 -1
  161. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  162. package/dist/features/layout/SideActionDock.js +52 -2
  163. package/dist/features/layout/TitleBarLayout.js +13 -4
  164. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  165. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  166. package/dist/features/layout/useCtaReveal.js +17 -26
  167. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  168. package/dist/features/ledger/repository/journal.repository.js +312 -0
  169. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  170. package/dist/features/ledger/schemas/expenses.js +27 -0
  171. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  172. package/dist/features/ledger/schemas/firestore.js +69 -0
  173. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  174. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  175. package/dist/features/orders/components/RaiseDisputeForm.js +19 -11
  176. package/dist/features/orders/repository/orders.repository.d.ts +28 -1
  177. package/dist/features/orders/repository/orders.repository.js +60 -6
  178. package/dist/features/orders/schemas/balance.d.ts +40 -0
  179. package/dist/features/orders/schemas/balance.js +47 -0
  180. package/dist/features/orders/schemas/firestore.d.ts +202 -0
  181. package/dist/features/orders/schemas/firestore.js +43 -0
  182. package/dist/features/orders/schemas/index.d.ts +2 -2
  183. package/dist/features/orders/types/index.d.ts +21 -0
  184. package/dist/features/payments/repository/payout.repository.js +3 -2
  185. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  186. package/dist/features/payments/schemas/firestore.js +23 -0
  187. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  188. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  189. package/dist/features/products/schemas/firestore.d.ts +26 -1
  190. package/dist/features/products/schemas/firestore.js +2 -0
  191. package/dist/features/products/schemas/index.d.ts +2 -2
  192. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  193. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  194. package/dist/features/scams/repository/scammer.repository.js +2 -1
  195. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  196. package/dist/features/scams/schemas/firestore.js +2 -1
  197. package/dist/features/seller/actions/offer-actions.js +56 -0
  198. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  199. package/dist/features/seller/actions/seller-actions.js +4 -0
  200. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  201. package/dist/features/seller/components/DispatchForm.js +190 -0
  202. package/dist/features/seller/components/SellerOrdersView.js +94 -2
  203. package/dist/features/seller/components/index.d.ts +1 -0
  204. package/dist/features/seller/components/index.js +1 -0
  205. package/dist/features/seller/repository/offer.repository.js +4 -3
  206. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  207. package/dist/features/seller/schemas/firestore.js +3 -2
  208. package/dist/features/seller/schemas/index.d.ts +4 -4
  209. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  210. package/dist/features/seller/schemas/order-forms.js +41 -8
  211. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  212. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +39 -0
  213. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +55 -0
  214. package/dist/features/shipping-boxes/schemas/firestore.d.ts +2 -4
  215. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  216. package/dist/features/stores/repository/store.repository.js +27 -1
  217. package/dist/features/stores/schemas/firestore.d.ts +41 -0
  218. package/dist/features/stores/schemas/firestore.js +20 -0
  219. package/dist/features/stores/schemas/index.d.ts +6 -6
  220. package/dist/features/support/repository/support.repository.js +72 -6
  221. package/dist/features/support/schemas/firestore.d.ts +17 -0
  222. package/dist/features/support/schemas/index.d.ts +2 -2
  223. package/dist/index.d.ts +5 -0
  224. package/dist/index.js +19 -0
  225. package/dist/next/routing/route-map.d.ts +92 -0
  226. package/dist/next/routing/route-map.js +53 -0
  227. package/dist/react/contexts/SessionContext.d.ts +17 -1
  228. package/dist/schemas/registry.d.ts +22 -16
  229. package/dist/security/pii-schemas.d.ts +1 -1
  230. package/dist/security/pii-schemas.js +45 -0
  231. package/dist/server.d.ts +27 -1
  232. package/dist/server.js +144 -0
  233. package/dist/styles.css +349 -1
  234. package/dist/tailwind-utilities.css +1 -1
  235. package/dist/ui/components/Button.d.ts +10 -1
  236. package/dist/ui/components/Button.js +25 -3
  237. package/dist/ui/components/Chart.d.ts +63 -0
  238. package/dist/ui/components/Chart.js +169 -0
  239. package/dist/ui/components/Chart.style.css +214 -0
  240. package/dist/ui/components/Disclaimer.js +10 -1
  241. package/dist/ui/components/OverflowRow.js +54 -2
  242. package/dist/ui/components/OverflowRow.style.css +38 -0
  243. package/dist/ui/components/RichTextEditor.js +99 -8
  244. package/dist/ui/components/chart-spec.d.ts +68 -0
  245. package/dist/ui/components/chart-spec.js +140 -0
  246. package/dist/ui/components/index.style.css +1 -0
  247. package/dist/ui/components/surface-tokens.d.ts +1 -1
  248. package/dist/ui/components/surface-tokens.js +9 -0
  249. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  250. package/dist/ui/components/toolbar-collapse.js +10 -1
  251. package/dist/ui/index.d.ts +6 -0
  252. package/dist/ui/index.js +3 -0
  253. package/dist/ui/rich-text/RichText.d.ts +10 -1
  254. package/dist/ui/rich-text/RichText.js +33 -2
  255. package/dist/ui/rich-text/RichText.style.css +35 -0
  256. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  257. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  258. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  259. package/dist/ui/rich-text/chart-blocks.js +87 -0
  260. package/package.json +1 -1
  261. package/scripts/seed-cli.mjs +3 -0
package/dist/client.js CHANGED
@@ -440,6 +440,9 @@ export { PROTECTION_CLAIM_REASON_LABEL } from "./features/protection-claims/sche
440
440
  export { OrderCompletionPanel } from "./features/orders/components/OrderCompletionPanel.js";
441
441
  // Buyer-facing EMI schedule with a pay-any-instalment action.
442
442
  export { EmiInstallmentsPanel } from "./features/orders/components/EmiInstallmentsPanel.js";
443
+ // D55 — the pre-order balance collector's buyer panel and its write shapes.
444
+ export { BalancePaymentPanel } from "./features/orders/components/BalancePaymentPanel.js";
445
+ export { balanceProofSchema, balanceReviewSchema, } from "./features/orders/schemas/balance.js";
443
446
  export { CountdownDisplay } from "./ui/components/CountdownDisplay.js";
444
447
  export { OrderAddonBadges } from "./features/orders/components/OrderAddonBadges.js";
445
448
  // Manual-payment (cash / UPI / EMI) shared constants — pure data + predicates,
@@ -567,6 +570,15 @@ export { useProduct } from "./features/products/index.js";
567
570
  export { BUNDLE_COPY } from "./_internal/shared/features/categories/bundle-copy.js";
568
571
  export { useSiteSettings } from "./core/index.js";
569
572
  export { checkEmiEligibility, computeEmiSchedule, computeBuyerEmiQuote, } from "./_internal/shared/features/emi/schedule.js";
573
+ /*
574
+ * 0f — the checkout client needs to know which tenders can carry instalments
575
+ * so it can DISABLE an incompatible one with a reason rather than let the
576
+ * buyer pick it and be refused at submit. Same map the server refuses from, so
577
+ * the affordance and the rule cannot disagree.
578
+ */
579
+ export { emiTenderBlockReason, isTenderCompatibleWithEmi } from "./_internal/shared/features/emi/choice.js";
580
+ /* The derivation strings for the fee breakdown — pure, no I/O. */
581
+ export { explainCodHandlingFee, explainEmiSurcharge, explainGstOnPlatformFee, explainPlatformFee, } from "./_internal/shared/fees/explain.js";
570
582
  export { computeCodHandlingFee } from "./_internal/shared/fees/calculator.js"; // reexport-from-internal-ok: pure fee-calc utility consumed directly by public checkout UI (CheckoutRouteClient.tsx), same category as the sibling computeEmiSchedule/checkEmiEligibility re-export two lines above
571
583
  export { FAQPageContent } from "./features/faq/index.js";
572
584
  export { CategoryInlineSelect } from "./features/seller/components/CategoryInlineSelect.js";
@@ -603,6 +615,7 @@ export { raffleEntrySchema } from "./features/contact/schemas/inquiry-forms.js";
603
615
  export { orderCancelSchema, paymentProofSchema, } from "./features/orders/schemas/buyer-forms.js";
604
616
  export { scamReportFormSchema } from "./features/scams/schemas/report-form.js";
605
617
  export { sublistingCategoryFormSchema } from "./features/store-extensions/schemas/sublisting-category-form.js";
618
+ export { adCreativeFormSchema } from "./features/ads/schemas/creative-form.js";
606
619
  export { adminStoreUpdateSchema, announcementBarSchema, } from "./features/admin/schemas/admin-editor-forms.js";
607
620
  export { adminOrderUpdateSchema, employeeInviteSchema, hardBanReasonSchema, featureFlagsUpdateSchema, adminAdFormSchema, } from "./features/admin/schemas/admin-ops-forms.js";
608
621
  export { changeEmailSchema } from "./features/account/schemas/index.js";
@@ -98,6 +98,10 @@ export declare const ADMIN_ENDPOINTS: {
98
98
  /** The action-index control plane (W7 / D7) — GET the whole index, PATCH one override. */
99
99
  readonly ACTION_INDEX: "/api/admin/action-index";
100
100
  readonly AD_BY_ID: (id: string) => string;
101
+ /** D56 — the self-serve creative moderation queue. */
102
+ readonly AD_BOOKINGS: "/api/admin/ads/bookings";
103
+ /** D56 — approve or reject one creative. A rejection REQUIRES a note. */
104
+ readonly AD_BOOKING_MODERATE: (id: string) => string;
101
105
  readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
102
106
  readonly PRODUCTS: "/api/admin/products";
103
107
  readonly PRODUCT_BY_ID: (id: string) => string;
@@ -110,6 +114,7 @@ export declare const ADMIN_ENDPOINTS: {
110
114
  readonly ORDER_PAYMENT_VERIFY: (id: string) => string;
111
115
  readonly ORDER_PAYMENT_REUPLOAD: (id: string) => string;
112
116
  readonly ORDER_PAYMENT_REJECT_FRAUD: (id: string) => string;
117
+ readonly ORDER_BALANCE_REVIEW: (id: string) => string;
113
118
  readonly USERS: "/api/admin/users";
114
119
  readonly USERS_BULK: "/api/admin/users/bulk";
115
120
  readonly USER_BY_ID: (uid: string) => string;
@@ -286,6 +291,13 @@ export declare const CART_ENDPOINTS: {
286
291
  * is why there is no `/api/cart/points/amount`.
287
292
  */
288
293
  readonly POINTS: "/api/cart/points";
294
+ /**
295
+ * The instalment plan — a TENURE and nothing else. It lives on the cart,
296
+ * not in a checkout body, because the online path needs the same answer in
297
+ * two requests (`/api/payment/create-order` captures, `/api/payment/verify`
298
+ * writes the order). Same reasoning as `POINTS` and `ADDONS` above.
299
+ */
300
+ readonly EMI: "/api/cart/emi";
289
301
  readonly COUPON: "/api/cart/coupon";
290
302
  /**
291
303
  * Add a buyer-assembled group selection as ONE line. Separate from `GET`'s
@@ -461,6 +473,7 @@ export declare const ORDER_ENDPOINTS: {
461
473
  readonly BY_ID: (id: string) => string;
462
474
  readonly TRACK: (trackingId: string) => string;
463
475
  readonly PAYMENT_PROOF: (id: string) => string;
476
+ readonly BALANCE_PROOF: (id: string) => string;
464
477
  readonly DISPUTE: (id: string) => string;
465
478
  };
466
479
  export declare const PREORDER_ENDPOINTS: {
@@ -502,6 +515,17 @@ export declare const SELLER_ENDPOINTS: {
502
515
  readonly PRODUCTS: "/api/store/products";
503
516
  readonly ORDERS: "/api/store/orders";
504
517
  readonly ORDERS_BY_ID: (orderId: string) => string;
518
+ /**
519
+ * Dispatch — BOTH branches of `shipOrderSchema`'s discriminated union.
520
+ *
521
+ * `method: "custom"` records a carrier the seller posted themselves;
522
+ * `method: "platform"` enqueues a booking through our own account. One
523
+ * route, because they are one decision — a second endpoint for the
524
+ * platform branch would be the same handler behind two ceilings, which is
525
+ * Root Cause #85.
526
+ */
527
+ readonly ORDER_SHIP: (orderId: string) => string;
528
+ readonly ORDER_OPEN_BALANCE: (orderId: string) => string;
505
529
  readonly AUCTIONS: "/api/store/products";
506
530
  readonly COUPONS: "/api/store/coupons";
507
531
  readonly COUPON_BY_ID: (id: string) => string;
@@ -695,6 +719,10 @@ export declare const API_ENDPOINTS: {
695
719
  /** The action-index control plane (W7 / D7) — GET the whole index, PATCH one override. */
696
720
  readonly ACTION_INDEX: "/api/admin/action-index";
697
721
  readonly AD_BY_ID: (id: string) => string;
722
+ /** D56 — the self-serve creative moderation queue. */
723
+ readonly AD_BOOKINGS: "/api/admin/ads/bookings";
724
+ /** D56 — approve or reject one creative. A rejection REQUIRES a note. */
725
+ readonly AD_BOOKING_MODERATE: (id: string) => string;
698
726
  readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
699
727
  readonly PRODUCTS: "/api/admin/products";
700
728
  readonly PRODUCT_BY_ID: (id: string) => string;
@@ -707,6 +735,7 @@ export declare const API_ENDPOINTS: {
707
735
  readonly ORDER_PAYMENT_VERIFY: (id: string) => string;
708
736
  readonly ORDER_PAYMENT_REUPLOAD: (id: string) => string;
709
737
  readonly ORDER_PAYMENT_REJECT_FRAUD: (id: string) => string;
738
+ readonly ORDER_BALANCE_REVIEW: (id: string) => string;
710
739
  readonly USERS: "/api/admin/users";
711
740
  readonly USERS_BULK: "/api/admin/users/bulk";
712
741
  readonly USER_BY_ID: (uid: string) => string;
@@ -883,6 +912,13 @@ export declare const API_ENDPOINTS: {
883
912
  * is why there is no `/api/cart/points/amount`.
884
913
  */
885
914
  readonly POINTS: "/api/cart/points";
915
+ /**
916
+ * The instalment plan — a TENURE and nothing else. It lives on the cart,
917
+ * not in a checkout body, because the online path needs the same answer in
918
+ * two requests (`/api/payment/create-order` captures, `/api/payment/verify`
919
+ * writes the order). Same reasoning as `POINTS` and `ADDONS` above.
920
+ */
921
+ readonly EMI: "/api/cart/emi";
886
922
  readonly COUPON: "/api/cart/coupon";
887
923
  /**
888
924
  * Add a buyer-assembled group selection as ONE line. Separate from `GET`'s
@@ -1005,6 +1041,7 @@ export declare const API_ENDPOINTS: {
1005
1041
  readonly BY_ID: (id: string) => string;
1006
1042
  readonly TRACK: (trackingId: string) => string;
1007
1043
  readonly PAYMENT_PROOF: (id: string) => string;
1044
+ readonly BALANCE_PROOF: (id: string) => string;
1008
1045
  readonly DISPUTE: (id: string) => string;
1009
1046
  };
1010
1047
  readonly PREORDERS: {
@@ -1043,6 +1080,17 @@ export declare const API_ENDPOINTS: {
1043
1080
  readonly PRODUCTS: "/api/store/products";
1044
1081
  readonly ORDERS: "/api/store/orders";
1045
1082
  readonly ORDERS_BY_ID: (orderId: string) => string;
1083
+ /**
1084
+ * Dispatch — BOTH branches of `shipOrderSchema`'s discriminated union.
1085
+ *
1086
+ * `method: "custom"` records a carrier the seller posted themselves;
1087
+ * `method: "platform"` enqueues a booking through our own account. One
1088
+ * route, because they are one decision — a second endpoint for the
1089
+ * platform branch would be the same handler behind two ceilings, which is
1090
+ * Root Cause #85.
1091
+ */
1092
+ readonly ORDER_SHIP: (orderId: string) => string;
1093
+ readonly ORDER_OPEN_BALANCE: (orderId: string) => string;
1046
1094
  readonly AUCTIONS: "/api/store/products";
1047
1095
  readonly COUPONS: "/api/store/coupons";
1048
1096
  readonly COUPON_BY_ID: (id: string) => string;
@@ -1257,6 +1305,10 @@ export declare const API_ROUTES: {
1257
1305
  /** The action-index control plane (W7 / D7) — GET the whole index, PATCH one override. */
1258
1306
  readonly ACTION_INDEX: "/api/admin/action-index";
1259
1307
  readonly AD_BY_ID: (id: string) => string;
1308
+ /** D56 — the self-serve creative moderation queue. */
1309
+ readonly AD_BOOKINGS: "/api/admin/ads/bookings";
1310
+ /** D56 — approve or reject one creative. A rejection REQUIRES a note. */
1311
+ readonly AD_BOOKING_MODERATE: (id: string) => string;
1260
1312
  readonly PAYMENTS_SETTINGS: "/api/admin/payments/settings";
1261
1313
  readonly PRODUCTS: "/api/admin/products";
1262
1314
  readonly PRODUCT_BY_ID: (id: string) => string;
@@ -1269,6 +1321,7 @@ export declare const API_ROUTES: {
1269
1321
  readonly ORDER_PAYMENT_VERIFY: (id: string) => string;
1270
1322
  readonly ORDER_PAYMENT_REUPLOAD: (id: string) => string;
1271
1323
  readonly ORDER_PAYMENT_REJECT_FRAUD: (id: string) => string;
1324
+ readonly ORDER_BALANCE_REVIEW: (id: string) => string;
1272
1325
  readonly USERS: "/api/admin/users";
1273
1326
  readonly USERS_BULK: "/api/admin/users/bulk";
1274
1327
  readonly USER_BY_ID: (uid: string) => string;
@@ -1445,6 +1498,13 @@ export declare const API_ROUTES: {
1445
1498
  * is why there is no `/api/cart/points/amount`.
1446
1499
  */
1447
1500
  readonly POINTS: "/api/cart/points";
1501
+ /**
1502
+ * The instalment plan — a TENURE and nothing else. It lives on the cart,
1503
+ * not in a checkout body, because the online path needs the same answer in
1504
+ * two requests (`/api/payment/create-order` captures, `/api/payment/verify`
1505
+ * writes the order). Same reasoning as `POINTS` and `ADDONS` above.
1506
+ */
1507
+ readonly EMI: "/api/cart/emi";
1448
1508
  readonly COUPON: "/api/cart/coupon";
1449
1509
  /**
1450
1510
  * Add a buyer-assembled group selection as ONE line. Separate from `GET`'s
@@ -1567,6 +1627,7 @@ export declare const API_ROUTES: {
1567
1627
  readonly BY_ID: (id: string) => string;
1568
1628
  readonly TRACK: (trackingId: string) => string;
1569
1629
  readonly PAYMENT_PROOF: (id: string) => string;
1630
+ readonly BALANCE_PROOF: (id: string) => string;
1570
1631
  readonly DISPUTE: (id: string) => string;
1571
1632
  };
1572
1633
  readonly PREORDERS: {
@@ -1605,6 +1666,17 @@ export declare const API_ROUTES: {
1605
1666
  readonly PRODUCTS: "/api/store/products";
1606
1667
  readonly ORDERS: "/api/store/orders";
1607
1668
  readonly ORDERS_BY_ID: (orderId: string) => string;
1669
+ /**
1670
+ * Dispatch — BOTH branches of `shipOrderSchema`'s discriminated union.
1671
+ *
1672
+ * `method: "custom"` records a carrier the seller posted themselves;
1673
+ * `method: "platform"` enqueues a booking through our own account. One
1674
+ * route, because they are one decision — a second endpoint for the
1675
+ * platform branch would be the same handler behind two ceilings, which is
1676
+ * Root Cause #85.
1677
+ */
1678
+ readonly ORDER_SHIP: (orderId: string) => string;
1679
+ readonly ORDER_OPEN_BALANCE: (orderId: string) => string;
1608
1680
  readonly AUCTIONS: "/api/store/products";
1609
1681
  readonly COUPONS: "/api/store/coupons";
1610
1682
  readonly COUPON_BY_ID: (id: string) => string;
@@ -129,6 +129,10 @@ export const ADMIN_ENDPOINTS = {
129
129
  /** The action-index control plane (W7 / D7) — GET the whole index, PATCH one override. */
130
130
  ACTION_INDEX: "/api/admin/action-index",
131
131
  AD_BY_ID: (id) => `/api/admin/ads/${id}`,
132
+ /** D56 — the self-serve creative moderation queue. */
133
+ AD_BOOKINGS: "/api/admin/ads/bookings",
134
+ /** D56 — approve or reject one creative. A rejection REQUIRES a note. */
135
+ AD_BOOKING_MODERATE: (id) => `/api/admin/ads/bookings/${id}/moderate`,
132
136
  PAYMENTS_SETTINGS: "/api/admin/payments/settings",
133
137
  PRODUCTS: "/api/admin/products",
134
138
  PRODUCT_BY_ID: (id) => `/api/admin/products/${id}`,
@@ -141,6 +145,12 @@ export const ADMIN_ENDPOINTS = {
141
145
  ORDER_PAYMENT_VERIFY: (id) => `/api/admin/orders/${id}/payment-verify`,
142
146
  ORDER_PAYMENT_REUPLOAD: (id) => `/api/admin/orders/${id}/payment-reupload`,
143
147
  ORDER_PAYMENT_REJECT_FRAUD: (id) => `/api/admin/orders/${id}/payment-reject-fraud`,
148
+ /*
149
+ * D55 — approve or reject a pre-order BALANCE proof. Separate from the
150
+ * three `ORDER_PAYMENT_*` routes above, which review the DEPOSIT: the two
151
+ * payments are months apart and each carries its own proof, status and note.
152
+ */
153
+ ORDER_BALANCE_REVIEW: (id) => `/api/admin/orders/${id}/balance-review`,
144
154
  USERS: "/api/admin/users",
145
155
  USERS_BULK: "/api/admin/users/bulk",
146
156
  USER_BY_ID: (uid) => `/api/admin/users/${uid}`,
@@ -339,6 +349,13 @@ export const CART_ENDPOINTS = {
339
349
  * is why there is no `/api/cart/points/amount`.
340
350
  */
341
351
  POINTS: "/api/cart/points",
352
+ /**
353
+ * The instalment plan — a TENURE and nothing else. It lives on the cart,
354
+ * not in a checkout body, because the online path needs the same answer in
355
+ * two requests (`/api/payment/create-order` captures, `/api/payment/verify`
356
+ * writes the order). Same reasoning as `POINTS` and `ADDONS` above.
357
+ */
358
+ EMI: "/api/cart/emi",
342
359
  COUPON: "/api/cart/coupon",
343
360
  /**
344
361
  * Add a buyer-assembled group selection as ONE line. Separate from `GET`'s
@@ -589,6 +606,13 @@ export const ORDER_ENDPOINTS = {
589
606
  BY_ID: (id) => `/api/orders/${id}`,
590
607
  TRACK: (trackingId) => `/api/orders/track/${trackingId}`,
591
608
  PAYMENT_PROOF: (id) => `/api/orders/${id}/payment-proof`,
609
+ /*
610
+ * D55 — proof of paying a pre-order BALANCE. Deliberately a separate
611
+ * endpoint from `PAYMENT_PROOF`, which is the DEPOSIT's: a pre-order has
612
+ * two payments months apart, and writing the second over the first would
613
+ * destroy the evidence for the payment that created the order.
614
+ */
615
+ BALANCE_PROOF: (id) => `/api/orders/${id}/balance-proof`,
592
616
  DISPUTE: (id) => `/api/orders/${id}/dispute`,
593
617
  };
594
618
  // ---------------------------------------------------------------------------
@@ -657,6 +681,23 @@ export const SELLER_ENDPOINTS = {
657
681
  PRODUCTS: "/api/store/products",
658
682
  ORDERS: "/api/store/orders",
659
683
  ORDERS_BY_ID: (orderId) => `/api/store/orders/${orderId}`,
684
+ /**
685
+ * Dispatch — BOTH branches of `shipOrderSchema`'s discriminated union.
686
+ *
687
+ * `method: "custom"` records a carrier the seller posted themselves;
688
+ * `method: "platform"` enqueues a booking through our own account. One
689
+ * route, because they are one decision — a second endpoint for the
690
+ * platform branch would be the same handler behind two ceilings, which is
691
+ * Root Cause #85.
692
+ */
693
+ ORDER_SHIP: (orderId) => `/api/store/orders/${orderId}/ship`,
694
+ /*
695
+ * D55 — "the goods have landed, the balance is now payable". An EVENT, not
696
+ * a derived state: a pre-order's premise is that the item does not exist
697
+ * yet, so the balance becomes collectable when the seller says stock
698
+ * arrived, and the buyer's 7-day window runs from that moment.
699
+ */
700
+ ORDER_OPEN_BALANCE: (orderId) => `/api/store/orders/${orderId}/open-balance`,
660
701
  AUCTIONS: "/api/store/products",
661
702
  COUPONS: "/api/store/coupons",
662
703
  COUPON_BY_ID: (id) => `/api/store/coupons/${id}`,
@@ -230,6 +230,17 @@ export declare const ORDER_FIELDS: {
230
230
  readonly TOTAL_AMOUNT: "totalAmount";
231
231
  readonly BUYER_ID: "buyerId";
232
232
  readonly BUNDLE_ID: "bundleId";
233
+ /**
234
+ * Which checkout LANE produced this order (`standard` / `auction` / `offer`
235
+ * / `preorder` / `prize-draw`) — see § "Checkout Lanes".
236
+ *
237
+ * 🛑 Never filter `orderType == "standard"` in a query. Orders written
238
+ * before the field existed carry no value at all, and a Firestore equality
239
+ * cannot match an absent field, so that filter silently drops every legacy
240
+ * order. `UserOrdersView` filters the standard lane in memory for exactly
241
+ * this reason; the other four values are safe as equalities.
242
+ */
243
+ readonly ORDER_TYPE: "orderType";
233
244
  readonly CREATED_AT: "createdAt";
234
245
  readonly UPDATED_AT: "updatedAt";
235
246
  readonly PAYMENT_DEADLINE: "paymentDeadline";
@@ -1000,6 +1011,36 @@ export declare const REFUND_CLAIM_FIELDS: {
1000
1011
  export declare const PRICE_OBSERVATION_FIELDS: {
1001
1012
  readonly CATEGORY_ID: "categoryId";
1002
1013
  };
1014
+ /**
1015
+ * A TTL-bounded hold on units of a product. See
1016
+ * `features/inventory/schemas/stock-reservation.ts` for why a reservation is
1017
+ * its own document rather than a counter on the product: the row and the
1018
+ * counter move in ONE transaction, so a crash between them is impossible.
1019
+ */
1020
+ export declare const STOCK_RESERVATION_FIELDS: {
1021
+ readonly PRODUCT_ID: "productId";
1022
+ readonly QUANTITY: "quantity";
1023
+ readonly HOLDER_KIND: "holderKind";
1024
+ readonly HOLDER_ID: "holderId";
1025
+ readonly CREATED_BY: "createdBy";
1026
+ readonly STATUS: "status";
1027
+ readonly EXPIRES_AT: "expiresAt";
1028
+ readonly ENDED_AT: "endedAt";
1029
+ readonly ENDED_REASON: "endedReason";
1030
+ };
1031
+ /**
1032
+ * One advertiser's booking of one placement for one period. The document id
1033
+ * IS the lock (`adBookingId`), so there is deliberately no `period`+`placementId`
1034
+ * uniqueness query to write — see `features/ads/schemas/firestore.ts`.
1035
+ */
1036
+ export declare const AD_BOOKING_FIELDS: {
1037
+ readonly PLACEMENT_ID: "placementId";
1038
+ readonly PERIOD: "period";
1039
+ readonly ADVERTISER_UID: "advertiserUid";
1040
+ readonly PAYMENT_STATE: "paymentState";
1041
+ readonly CANCELLED_AT: "cancelledAt";
1042
+ readonly CREATED_AT: "createdAt";
1043
+ };
1003
1044
  export declare const OAUTH_STATE_VALUES: {
1004
1045
  readonly PENDING: "pending";
1005
1046
  readonly USED: "used";
@@ -258,6 +258,17 @@ export const ORDER_FIELDS = {
258
258
  TOTAL_AMOUNT: "totalAmount",
259
259
  BUYER_ID: "buyerId",
260
260
  BUNDLE_ID: "bundleId",
261
+ /**
262
+ * Which checkout LANE produced this order (`standard` / `auction` / `offer`
263
+ * / `preorder` / `prize-draw`) — see § "Checkout Lanes".
264
+ *
265
+ * 🛑 Never filter `orderType == "standard"` in a query. Orders written
266
+ * before the field existed carry no value at all, and a Firestore equality
267
+ * cannot match an absent field, so that filter silently drops every legacy
268
+ * order. `UserOrdersView` filters the standard lane in memory for exactly
269
+ * this reason; the other four values are safe as equalities.
270
+ */
271
+ ORDER_TYPE: "orderType",
261
272
  CREATED_AT: "createdAt",
262
273
  UPDATED_AT: "updatedAt",
263
274
  PAYMENT_DEADLINE: "paymentDeadline",
@@ -1203,6 +1214,42 @@ export const PRICE_OBSERVATION_FIELDS = {
1203
1214
  CATEGORY_ID: "categoryId",
1204
1215
  };
1205
1216
  // ============================================================================
1217
+ // STOCK RESERVATIONS
1218
+ // ============================================================================
1219
+ /**
1220
+ * A TTL-bounded hold on units of a product. See
1221
+ * `features/inventory/schemas/stock-reservation.ts` for why a reservation is
1222
+ * its own document rather than a counter on the product: the row and the
1223
+ * counter move in ONE transaction, so a crash between them is impossible.
1224
+ */
1225
+ export const STOCK_RESERVATION_FIELDS = {
1226
+ PRODUCT_ID: "productId",
1227
+ QUANTITY: "quantity",
1228
+ HOLDER_KIND: "holderKind",
1229
+ HOLDER_ID: "holderId",
1230
+ CREATED_BY: "createdBy",
1231
+ STATUS: "status",
1232
+ EXPIRES_AT: "expiresAt",
1233
+ ENDED_AT: "endedAt",
1234
+ ENDED_REASON: "endedReason",
1235
+ };
1236
+ // ============================================================================
1237
+ // AD BOOKINGS
1238
+ // ============================================================================
1239
+ /**
1240
+ * One advertiser's booking of one placement for one period. The document id
1241
+ * IS the lock (`adBookingId`), so there is deliberately no `period`+`placementId`
1242
+ * uniqueness query to write — see `features/ads/schemas/firestore.ts`.
1243
+ */
1244
+ export const AD_BOOKING_FIELDS = {
1245
+ PLACEMENT_ID: "placementId",
1246
+ PERIOD: "period",
1247
+ ADVERTISER_UID: "advertiserUid",
1248
+ PAYMENT_STATE: "paymentState",
1249
+ CANCELLED_AT: "cancelledAt",
1250
+ CREATED_AT: "createdAt",
1251
+ };
1252
+ // ============================================================================
1206
1253
  // OAUTH STATE VALUES
1207
1254
  // ============================================================================
1208
1255
  export const OAUTH_STATE_VALUES = {
@@ -64,9 +64,25 @@ const SORT_OPTIONS = [
64
64
  * clause is silently dropped and the chip returns the ENTIRE order list while
65
65
  * looking like a filter (Root Cause #62).
66
66
  */
67
+ /*
68
+ * 🛑 MEASURED 2026-10-22 — this chip group was INERT, and the comment above it
69
+ * explained why it should not have been while describing the wrong half.
70
+ *
71
+ * `buildFilters` emits `paymentMethod==emi` inside `filters`, and
72
+ * `/api/user/orders` regex-extracts only `status==` and `orderType==` from
73
+ * that string. Every other clause is silently dropped — so all three chips
74
+ * returned the buyer's ENTIRE order list while looking exactly like a working
75
+ * filter. The note above was careful about the SIEVE allowlist (Root Cause
76
+ * #62) and the route's own parser was the break, one layer earlier.
77
+ *
78
+ * 🛑 And "EMI plans" could not be a `paymentMethod` value any more regardless:
79
+ * since 0f an instalment order's tender is `online` / `upi_manual` / `cash`,
80
+ * so the id is now `emiEnabled`, refined in memory by the route alongside the
81
+ * other two. `cod` and `online` stay real stored `paymentMethod` values.
82
+ */
67
83
  const PAYMENT_METHOD_TABS = [
68
84
  { id: "", label: "Any" },
69
- { id: "emi", label: "EMI plans" },
85
+ { id: "emiEnabled", label: "EMI plans" },
70
86
  { id: "cod", label: "Cash on delivery" },
71
87
  { id: "online", label: "Paid online" },
72
88
  ];
@@ -134,7 +150,17 @@ export function UserOrdersView({ onOrderClick }) {
134
150
  buildFilters: (state) => [
135
151
  state.status ? sieveFilter("status", SIEVE_OP.EQ, state.status) : null,
136
152
  state.orderType ? sieveFilter("orderType", SIEVE_OP.EQ, state.orderType) : null,
137
- state.paymentMethod ? sieveFilter("paymentMethod", SIEVE_OP.EQ, state.paymentMethod) : null,
153
+ /*
154
+ * 🛑 `emiEnabled` is NOT a `paymentMethod`, so it gets its own clause
155
+ * key — the route refines both in memory (see its note), and emitting
156
+ * `paymentMethod==emiEnabled` would be a filter for a value no order
157
+ * can hold.
158
+ */
159
+ state.paymentMethod
160
+ ? state.paymentMethod === "emiEnabled"
161
+ ? sieveFilter("emiEnabled", SIEVE_OP.EQ, "true")
162
+ : sieveFilter("paymentMethod", SIEVE_OP.EQ, state.paymentMethod)
163
+ : null,
138
164
  ]
139
165
  .filter(Boolean)
140
166
  .join(",") || undefined,
@@ -0,0 +1,55 @@
1
+ import React from "react";
2
+ import { type IntegrationPatch } from "../../../_internal/shared/features/admin/integrations";
3
+ import type { SiteSettingsDocument } from "../schemas/firestore";
4
+ /**
5
+ * Admin → Site → Integrations. The four switches that decide whether we take
6
+ * money online, send customer email, book couriers, and offer buyers a support
7
+ * surface.
8
+ *
9
+ * ## Why this page exists rather than a Site Settings tab
10
+ *
11
+ * A kill switch for payments has to be findable without hunting a tab strip.
12
+ * It is also the one surface where the four switches are visible TOGETHER,
13
+ * which matters because their off-states are not comparable: three of them
14
+ * stop something and one of them selects a working alternative.
15
+ *
16
+ * ## 🛑 The model is the authority; this file renders it
17
+ *
18
+ * Every label, summary, consequence, severity and settings path comes from
19
+ * `INTEGRATIONS`, and the current state comes from `readIntegrationStates` —
20
+ * **the same expression the route guards resolve through**. That is the whole
21
+ * point: `withOnlinePaymentEnabled` used to hand-write the payments half, and
22
+ * the first draft of the model reproduced it WRONG (it read `razorpayEnabled`
23
+ * alone against a guard that is an OR across both gateways), so with PhonePe
24
+ * on and Razorpay off a page would have reported "payments OFF" while all six
25
+ * `/api/payment` routes were open and taking money.
26
+ *
27
+ * So this view must never derive a state, a consequence or a field name of its
28
+ * own. If a row needs a new fact, it goes on the descriptor.
29
+ *
30
+ * ## 🛑 `offConsequence` IS the confirmation body
31
+ *
32
+ * The registry's `disable-integration` ActionDef deliberately ships an empty
33
+ * `body`, because the consequence differs per integration and copying each
34
+ * string into the registry would be a second place for it to drift from. The
35
+ * dialog is composed here, from the descriptor, at render time.
36
+ */
37
+ export interface AdminIntegrationsViewProps {
38
+ /**
39
+ * The settings document, server-fetched.
40
+ *
41
+ * 🛑 `Partial` because this page must render against an older document that
42
+ * predates `support.enabled`. `readIntegrationStates` chooses a per-field
43
+ * default for exactly that case — and they are NOT a uniform `?? false`:
44
+ * email and support default ON, because a missing field must not read as
45
+ * "we stopped talking to customers".
46
+ */
47
+ settings: Partial<SiteSettingsDocument> | null;
48
+ /**
49
+ * Persist a settings patch. Supplied by the consumer page so this component
50
+ * carries no endpoint and no fetch — `PUT /api/admin/site`, which already
51
+ * records one `recordAdminAction` per write.
52
+ */
53
+ onSave: (patch: IntegrationPatch) => Promise<void>;
54
+ }
55
+ export declare function AdminIntegrationsView({ settings, onSave }: AdminIntegrationsViewProps): React.JSX.Element;
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import { Alert, Badge, Button, Div, Heading, Row, Stack, Text, } from "../../../ui/index.js";
5
+ import { useToast } from "../../../ui/components/Toast.js";
6
+ import { normalizeError } from "../../../errors/normalize.js";
7
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
8
+ import { INTEGRATIONS, INTEGRATION_ORDER, allIntegrationsPatch, integrationPatch, readIntegrationStates, } from "../../../_internal/shared/features/admin/integrations.js";
9
+ /** What the switch currently is, in the admin's vocabulary rather than a boolean. */
10
+ function stateLabel(id, enabled) {
11
+ /*
12
+ * 🛑 Shipping is NOT on/off, and this is the one row where saying so matters.
13
+ *
14
+ * "Off" selects `provider: "manual"` — the self-ship flow sellers already
15
+ * use and claim postage back through. Rendering that as "Disabled" beside
16
+ * three switches that genuinely stop things would invite an admin to read it
17
+ * as "shipping is broken", and the descriptor's own note says the switch
18
+ * "selects manual rather than stopping anything".
19
+ */
20
+ if (id === "shipping")
21
+ return enabled ? "We book couriers" : "Sellers self-ship";
22
+ return enabled ? "On" : "Off";
23
+ }
24
+ export function AdminIntegrationsView({ settings, onSave }) {
25
+ const { showToast } = useToast();
26
+ const [pending, setPending] = useState(null);
27
+ /*
28
+ * 🛑 Derived from the prop, NOT copied into state.
29
+ *
30
+ * A `useState(readIntegrationStates(settings))` would go stale the moment
31
+ * the page refetched, and the staleness would be invisible: the row would
32
+ * read "On" while the guard enforcing it read "off". This page's entire job
33
+ * is to agree with the guard, so it re-derives rather than remembers.
34
+ */
35
+ const states = useMemo(() => readIntegrationStates(settings), [settings]);
36
+ const apply = useCallback(async (key, patch, label) => {
37
+ setPending(key);
38
+ try {
39
+ await onSave(patch);
40
+ showToast(`${label} saved.`, "success");
41
+ }
42
+ catch (err) {
43
+ void normalizeError(err);
44
+ /*
45
+ * 🛑 No optimistic flip anywhere in this component, so a failure needs
46
+ * no rollback — the row still shows what the server last told us. On a
47
+ * kill switch the cost of the two mistakes is wildly asymmetric: a
48
+ * row that briefly lags is a nuisance, while a row claiming "payments
49
+ * off" over a live gateway is the failure the model's own header warns
50
+ * about.
51
+ */
52
+ showToast(`Couldn't save ${label.toLowerCase()}. Nothing was changed.`, "error");
53
+ }
54
+ finally {
55
+ setPending(null);
56
+ }
57
+ }, [onSave, showToast]);
58
+ return (_jsxs(Stack, { gap: "lg", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, size: "xl", weight: "semibold", color: "primary", children: "Integrations" }), _jsx(Text, { size: "sm", color: "muted", children: "What the platform talks to, and what happens when it stops. Each switch writes the same settings field the code enforcing it reads." })] }), _jsx(Alert, { variant: "warning", title: "Switch payments off only when nobody is checking out", children: "Turning online payments off also closes the routes that FINISH a payment, including the gateway webhook. A buyer part-way through the gateway can be charged without an order being placed, and the gateway will not retry. There is no safe mid-checkout moment." }), _jsx(Stack, { gap: "md", children: INTEGRATION_ORDER.map((id) => {
59
+ const d = INTEGRATIONS[id];
60
+ const enabled = states[id].enabled;
61
+ const busy = pending === id || pending === "all";
62
+ const action = enabled
63
+ ? ACTIONS.ADMIN["disable-integration"]
64
+ : ACTIONS.ADMIN["enable-integration"];
65
+ return (_jsx(Div, { surface: d.severe && enabled ? "warning-surface" : "card", padding: "md", rounded: "lg", border: "default", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { align: "start", justify: "between", gap: "md", className: "min-w-0", children: [_jsxs(Stack, { gap: "xs", className: "min-w-0", children: [_jsxs(Row, { align: "center", gap: "sm", className: "min-w-0", children: [_jsx(Text, { weight: "semibold", color: "primary", className: "min-w-0", children: d.label }), _jsx(Badge, { variant: enabled ? "success" : "inactive", children: stateLabel(id, enabled) }), d.severe && _jsx(Badge, { variant: "warning", children: "High impact" })] }), _jsx(Text, { size: "sm", color: "muted", children: d.summary })] }), _jsx(Button, { action: action,
66
+ /*
67
+ * 🛑 The dialog body is composed HERE from the descriptor.
68
+ * The ActionDef ships an empty body on purpose — see its
69
+ * note. A per-integration consequence copied into the
70
+ * registry would be a second source for one sentence.
71
+ */
72
+ confirmationBody: enabled ? d.offConsequence : undefined, isLoading: busy, disabled: busy, onClick: () => apply(id, integrationPatch(id, !enabled), `${d.label} ${enabled ? "off" : "on"}`) })] }), _jsxs(Text, { size: "xs", color: "muted", children: [_jsxs(Text, { as: "span", size: "xs", weight: "semibold", color: "muted", children: ["Off means:", " "] }), d.offConsequence] }), _jsxs(Row, { align: "center", gap: "sm", className: "min-w-0", children: [_jsx(Text, { size: "xs", color: "faint", numeric: true, className: "min-w-0", truncate: 1, children: d.field }), _jsx(Text, { size: "xs", color: "faint", children: "\u00B7" }), _jsx(Text, { size: "xs", color: "faint", className: "min-w-0", truncate: 1, children: d.routeGuard === "gated" ? "API routes close when off" : "no route gate" })] })] }) }, id));
73
+ }) }), _jsxs(Row, { align: "center", gap: "sm", border: "top-subtle", padding: "t-md", children: [_jsx(Button, { action: ACTIONS.ADMIN["enable-all-integrations"], isLoading: pending === "all", disabled: pending !== null, onClick: () => apply("all", allIntegrationsPatch(true), "All integrations on") }), _jsx(Button, { action: ACTIONS.ADMIN["disable-all-integrations"], isLoading: pending === "all", disabled: pending !== null, onClick: () => apply("all", allIntegrationsPatch(false), "All integrations off") })] })] }));
74
+ }
@@ -53,5 +53,20 @@ export interface AdminOrderEditorViewProps {
53
53
  sourceContext?: OrderSourceContext;
54
54
  /** For the provenance card's money formatting; falls back to the default. */
55
55
  currency?: string;
56
+ /**
57
+ * D55 — the pre-order balance block, present once a seller has opened it.
58
+ *
59
+ * 🛑 Admin is the ONLY role that sees `proofUrl` here, matching the deposit:
60
+ * the seller's own endpoint strips it, because a bank screenshot is the
61
+ * buyer's and verification is not the seller's job. Reviewing a payment to
62
+ * yourself is not a review.
63
+ */
64
+ balance?: {
65
+ amount: number;
66
+ status: "awaiting" | "submitted" | "paid" | "rejected";
67
+ proofUrl?: string;
68
+ transactionId?: string;
69
+ reviewNote?: string;
70
+ };
56
71
  }
57
- export declare function AdminOrderEditorView({ open, onClose, orderId, orderLabel, currentStatus, items, sourceContext, currency, paymentProofUrl, paymentTransactionId, paymentMethod, paymentStatus, displayedUpiId, buyerReportedUpiId, paymentUpiMismatch, buyerMarkedPaid, buyerFraudAgreementAccepted, paymentReviewOutcome, addons, }: AdminOrderEditorViewProps): React.JSX.Element;
72
+ export declare function AdminOrderEditorView({ open, onClose, orderId, orderLabel, currentStatus, items, sourceContext, currency, paymentProofUrl, paymentTransactionId, paymentMethod, paymentStatus, displayedUpiId, buyerReportedUpiId, paymentUpiMismatch, buyerMarkedPaid, buyerFraudAgreementAccepted, paymentReviewOutcome, addons, balance, }: AdminOrderEditorViewProps): React.JSX.Element;