@mohasinac/appkit 4.62.0 → 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 (391) 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 +129 -9
  8. package/dist/_internal/server/features/checkout/actions.js +850 -79
  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/invoicing/allocate.d.ts +63 -0
  22. package/dist/_internal/server/features/invoicing/allocate.js +162 -0
  23. package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
  24. package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
  25. package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
  26. package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
  27. package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
  28. package/dist/_internal/server/features/invoicing/issue.js +202 -0
  29. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  30. package/dist/_internal/server/features/offers/destinations.js +65 -0
  31. package/dist/_internal/server/features/orders/actions.d.ts +8 -1
  32. package/dist/_internal/server/features/orders/actions.js +81 -8
  33. package/dist/_internal/server/features/orders/adapters.js +54 -0
  34. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  35. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  36. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  37. package/dist/_internal/server/features/orders/balance.js +256 -0
  38. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
  39. package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
  40. package/dist/_internal/server/features/points/award.js +46 -4
  41. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  42. package/dist/_internal/server/features/pricing/actions.js +144 -0
  43. package/dist/_internal/server/features/refunds/actions.js +26 -0
  44. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  45. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  46. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  47. package/dist/_internal/server/features/shipping/book.js +176 -0
  48. package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
  49. package/dist/_internal/server/features/shipping/courier-block.js +264 -0
  50. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  51. package/dist/_internal/server/features/site-settings/adapters.js +29 -0
  52. package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
  53. package/dist/_internal/server/features/stores/adapters.js +65 -0
  54. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  55. package/dist/_internal/server/functions/scheduled.js +95 -2
  56. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
  57. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
  58. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
  59. package/dist/_internal/server/jobs/core/index.d.ts +2 -1
  60. package/dist/_internal/server/jobs/core/index.js +2 -1
  61. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  62. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
  63. package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
  64. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
  65. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
  66. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
  67. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  68. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  69. package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
  70. package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
  71. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
  72. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  73. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  74. package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
  75. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  76. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  77. package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
  78. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  79. package/dist/_internal/shared/actions/action-registry.js +296 -0
  80. package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
  81. package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
  82. package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
  83. package/dist/_internal/shared/checkout/order-math.js +159 -0
  84. package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
  85. package/dist/_internal/shared/checkout/refundable-base.js +13 -1
  86. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  87. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  88. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  89. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  90. package/dist/_internal/shared/checkout/split.d.ts +75 -0
  91. package/dist/_internal/shared/checkout/split.js +120 -0
  92. package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
  93. package/dist/_internal/shared/content/disclaimers.js +217 -0
  94. package/dist/_internal/shared/content/published-values.d.ts +93 -0
  95. package/dist/_internal/shared/content/published-values.js +206 -0
  96. package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
  97. package/dist/_internal/shared/features/admin/integrations.js +263 -0
  98. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  99. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  100. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  101. package/dist/_internal/shared/features/emi/choice.js +69 -0
  102. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  103. package/dist/_internal/shared/features/emi/group.js +126 -0
  104. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  105. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  106. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  107. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  108. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  109. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  110. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  111. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  112. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  113. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  114. package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
  115. package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
  116. package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
  117. package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
  118. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  119. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  120. package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
  121. package/dist/_internal/shared/features/points/accepts.js +49 -0
  122. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  123. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  124. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  125. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  126. package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
  127. package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
  128. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  129. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  130. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  131. package/dist/_internal/shared/fees/calculator.d.ts +33 -1
  132. package/dist/_internal/shared/fees/calculator.js +32 -2
  133. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  134. package/dist/_internal/shared/fees/explain.js +101 -0
  135. package/dist/_internal/shared/history/index.d.ts +1 -1
  136. package/dist/_internal/shared/history/index.js +1 -1
  137. package/dist/_internal/shared/history/types.d.ts +7 -1
  138. package/dist/_internal/shared/history/types.js +25 -0
  139. package/dist/client.d.ts +21 -0
  140. package/dist/client.js +43 -0
  141. package/dist/constants/api-endpoints.d.ts +114 -0
  142. package/dist/constants/api-endpoints.js +55 -0
  143. package/dist/constants/field-names.d.ts +42 -0
  144. package/dist/constants/field-names.js +52 -0
  145. package/dist/contracts/index.d.ts +1 -1
  146. package/dist/contracts/shipping.d.ts +45 -0
  147. package/dist/contracts/shipping.js +15 -0
  148. package/dist/features/about/components/AboutView.js +1 -1
  149. package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
  150. package/dist/features/account/components/UserOrdersView.js +47 -35
  151. package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
  152. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  153. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  154. package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
  155. package/dist/features/admin/components/AdminInvoicingView.js +65 -0
  156. package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
  157. package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
  158. package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
  159. package/dist/features/admin/components/AdminOrdersView.js +86 -5
  160. package/dist/features/admin/components/OwnerQuickActions.js +24 -2
  161. package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
  162. package/dist/features/admin/constants/filter-tabs.js +6 -0
  163. package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
  164. package/dist/features/admin/hooks/useAdminListingData.js +16 -0
  165. package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
  166. package/dist/features/admin/schemas/firestore.d.ts +62 -0
  167. package/dist/features/admin/schemas/firestore.js +5 -0
  168. package/dist/features/ads/schemas/booking-write.d.ts +120 -0
  169. package/dist/features/ads/schemas/booking-write.js +75 -0
  170. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  171. package/dist/features/ads/schemas/creative-form.js +51 -0
  172. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  173. package/dist/features/ads/schemas/firestore.js +109 -0
  174. package/dist/features/auctions/repository/bid.repository.js +3 -1
  175. package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
  176. package/dist/features/audit-log/schemas/firestore.js +89 -0
  177. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  178. package/dist/features/auth/actions/profile-actions.js +62 -1
  179. package/dist/features/auth/permissions/constants.js +13 -0
  180. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  181. package/dist/features/auth/schemas/firestore.js +2 -1
  182. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  183. package/dist/features/blog/actions/blog-actions.js +17 -2
  184. package/dist/features/blog/api/route.js +4 -1
  185. package/dist/features/blog/columns/index.js +5 -0
  186. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  187. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  188. package/dist/features/blog/repository/blog.repository.js +5 -0
  189. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  190. package/dist/features/blog/schemas/blog-form.js +1 -0
  191. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  192. package/dist/features/blog/schemas/firestore.js +23 -0
  193. package/dist/features/blog/schemas/index.d.ts +6 -0
  194. package/dist/features/blog/schemas/index.js +2 -0
  195. package/dist/features/blog/types/index.d.ts +2 -0
  196. package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
  197. package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
  198. package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
  199. package/dist/features/cart/components/PointsTenderPicker.js +15 -0
  200. package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
  201. package/dist/features/cart/components/index.d.ts +2 -0
  202. package/dist/features/cart/components/index.js +1 -0
  203. package/dist/features/cart/repository/cart.repository.d.ts +33 -0
  204. package/dist/features/cart/repository/cart.repository.js +47 -0
  205. package/dist/features/cart/schemas/firestore.d.ts +116 -0
  206. package/dist/features/contact/email.d.ts +27 -10
  207. package/dist/features/contact/email.js +20 -3
  208. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  209. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  210. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  211. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  212. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  213. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  214. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
  215. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
  216. package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
  217. package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
  218. package/dist/features/events/components/EventSaleBanner.js +1 -1
  219. package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
  220. package/dist/features/faq/components/FAQAccordion.js +29 -4
  221. package/dist/features/faq/components/FAQPageContent.js +2 -2
  222. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  223. package/dist/features/homepage/schemas/index.d.ts +8 -8
  224. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  225. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  226. package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
  227. package/dist/features/invoicing/schemas/firestore.js +45 -0
  228. package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
  229. package/dist/features/invoicing/utils/financial-year.js +53 -0
  230. package/dist/features/jobs/actions/enqueue-job.js +18 -1
  231. package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
  232. package/dist/features/jobs/repository/jobs.repository.js +84 -1
  233. package/dist/features/jobs/schemas/firestore.d.ts +80 -0
  234. package/dist/features/jobs/schemas/firestore.js +37 -0
  235. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  236. package/dist/features/layout/AppLayoutShell.js +12 -4
  237. package/dist/features/layout/BottomActions.js +2 -1
  238. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  239. package/dist/features/layout/SideActionDock.js +52 -2
  240. package/dist/features/layout/TitleBarLayout.js +13 -4
  241. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  242. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  243. package/dist/features/layout/useCtaReveal.js +17 -26
  244. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  245. package/dist/features/ledger/repository/journal.repository.js +312 -0
  246. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  247. package/dist/features/ledger/schemas/expenses.js +27 -0
  248. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  249. package/dist/features/ledger/schemas/firestore.js +69 -0
  250. package/dist/features/lottery/schemas/zod.d.ts +6 -6
  251. package/dist/features/media/MediaImage.js +22 -1
  252. package/dist/features/media/upload/ImageUpload.js +1 -1
  253. package/dist/features/obligations/constants/policies.js +24 -1
  254. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  255. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  256. package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
  257. package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
  258. package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
  259. package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
  260. package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
  261. package/dist/features/orders/components/RefundRequestView.js +19 -1
  262. package/dist/features/orders/components/index.d.ts +4 -0
  263. package/dist/features/orders/components/index.js +2 -0
  264. package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
  265. package/dist/features/orders/constants/order-lane-tabs.js +88 -0
  266. package/dist/features/orders/repository/orders.repository.d.ts +85 -1
  267. package/dist/features/orders/repository/orders.repository.js +205 -6
  268. package/dist/features/orders/schemas/balance.d.ts +40 -0
  269. package/dist/features/orders/schemas/balance.js +47 -0
  270. package/dist/features/orders/schemas/firestore.d.ts +398 -1
  271. package/dist/features/orders/schemas/firestore.js +43 -0
  272. package/dist/features/orders/schemas/index.d.ts +56 -8
  273. package/dist/features/orders/schemas/index.js +12 -0
  274. package/dist/features/orders/types/index.d.ts +47 -0
  275. package/dist/features/orders/utils/courier-block.d.ts +25 -0
  276. package/dist/features/orders/utils/courier-block.js +23 -0
  277. package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
  278. package/dist/features/payment-cases/schemas/firestore.js +1 -0
  279. package/dist/features/payments/repository/payout.repository.js +3 -2
  280. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  281. package/dist/features/payments/schemas/firestore.js +23 -0
  282. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  283. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  284. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
  285. package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
  286. package/dist/features/products/components/ProductDetailPageView.js +2 -2
  287. package/dist/features/products/schemas/firestore.d.ts +26 -1
  288. package/dist/features/products/schemas/firestore.js +2 -0
  289. package/dist/features/products/schemas/index.d.ts +2 -2
  290. package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
  291. package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
  292. package/dist/features/promotions/actions/coupon-stacking.js +21 -2
  293. package/dist/features/promotions/components/CouponCard.js +13 -0
  294. package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
  295. package/dist/features/promotions/constants/coupon-help.js +9 -1
  296. package/dist/features/promotions/schemas/firestore.d.ts +24 -0
  297. package/dist/features/promotions/schemas/firestore.js +4 -0
  298. package/dist/features/promotions/types/index.d.ts +19 -1
  299. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  300. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  301. package/dist/features/scams/components/ScamProfileView.js +2 -2
  302. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  303. package/dist/features/scams/repository/scammer.repository.js +2 -1
  304. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  305. package/dist/features/scams/schemas/firestore.js +2 -1
  306. package/dist/features/search/action-index/tab-entries.js +1 -1
  307. package/dist/features/seller/actions/offer-actions.js +56 -0
  308. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  309. package/dist/features/seller/actions/seller-actions.js +37 -3
  310. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  311. package/dist/features/seller/components/DispatchForm.js +190 -0
  312. package/dist/features/seller/components/SellerOrdersView.js +221 -27
  313. package/dist/features/seller/components/index.d.ts +1 -0
  314. package/dist/features/seller/components/index.js +1 -0
  315. package/dist/features/seller/hooks/useSellerListingData.js +25 -0
  316. package/dist/features/seller/repository/offer.repository.js +4 -3
  317. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  318. package/dist/features/seller/schemas/firestore.js +3 -2
  319. package/dist/features/seller/schemas/index.d.ts +4 -4
  320. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  321. package/dist/features/seller/schemas/order-forms.js +41 -8
  322. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  323. package/dist/features/shipments/schemas/validation.d.ts +4 -4
  324. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
  325. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
  326. package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
  327. package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
  328. package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
  329. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
  330. package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
  331. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  332. package/dist/features/stores/repository/store.repository.js +27 -1
  333. package/dist/features/stores/schemas/firestore.d.ts +112 -0
  334. package/dist/features/stores/schemas/firestore.js +20 -0
  335. package/dist/features/stores/schemas/index.d.ts +6 -6
  336. package/dist/features/stores/types/index.d.ts +19 -0
  337. package/dist/features/support/repository/support.repository.js +72 -6
  338. package/dist/features/support/schemas/firestore.d.ts +17 -0
  339. package/dist/features/support/schemas/index.d.ts +8 -8
  340. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  341. package/dist/index.d.ts +11 -1
  342. package/dist/index.js +33 -1
  343. package/dist/next/routing/route-map.d.ts +112 -0
  344. package/dist/next/routing/route-map.js +63 -0
  345. package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
  346. package/dist/providers/shipping-shiprocket/index.js +84 -1
  347. package/dist/react/contexts/SessionContext.d.ts +17 -1
  348. package/dist/schemas/registry.d.ts +69 -34
  349. package/dist/schemas/sieve.d.ts +2 -2
  350. package/dist/security/pii-schemas.d.ts +1 -1
  351. package/dist/security/pii-schemas.js +45 -0
  352. package/dist/server-entry.d.ts +2 -2
  353. package/dist/server-entry.js +8 -1
  354. package/dist/server.d.ts +36 -1
  355. package/dist/server.js +183 -1
  356. package/dist/styles.css +412 -80
  357. package/dist/tailwind-utilities.css +1 -1
  358. package/dist/tokens/themes/default-dark.js +1 -0
  359. package/dist/tokens/themes/default-light.js +1 -0
  360. package/dist/tokens/themes/required.d.ts +1 -1
  361. package/dist/tokens/themes/required.js +1 -0
  362. package/dist/tokens/tokens.css +15 -0
  363. package/dist/ui/components/Button.d.ts +10 -1
  364. package/dist/ui/components/Button.js +25 -3
  365. package/dist/ui/components/Chart.d.ts +63 -0
  366. package/dist/ui/components/Chart.js +169 -0
  367. package/dist/ui/components/Chart.style.css +214 -0
  368. package/dist/ui/components/Disclaimer.d.ts +19 -0
  369. package/dist/ui/components/Disclaimer.js +83 -0
  370. package/dist/ui/components/OverflowRow.js +54 -2
  371. package/dist/ui/components/OverflowRow.style.css +38 -0
  372. package/dist/ui/components/RichTextEditor.js +99 -8
  373. package/dist/ui/components/chart-spec.d.ts +68 -0
  374. package/dist/ui/components/chart-spec.js +140 -0
  375. package/dist/ui/components/index.style.css +1 -0
  376. package/dist/ui/components/surface-tokens.d.ts +1 -1
  377. package/dist/ui/components/surface-tokens.js +9 -0
  378. package/dist/ui/components/tabs-overflow.js +64 -11
  379. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  380. package/dist/ui/components/toolbar-collapse.js +10 -1
  381. package/dist/ui/index.d.ts +8 -0
  382. package/dist/ui/index.js +9 -0
  383. package/dist/ui/rich-text/RichText.d.ts +10 -1
  384. package/dist/ui/rich-text/RichText.js +33 -2
  385. package/dist/ui/rich-text/RichText.style.css +83 -79
  386. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  387. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  388. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  389. package/dist/ui/rich-text/chart-blocks.js +87 -0
  390. package/package.json +1 -1
  391. package/scripts/seed-cli.mjs +1834 -1822
@@ -72,6 +72,29 @@ export interface CouponDocument extends BaseDocument {
72
72
  discount: DiscountConfig;
73
73
  bxgy?: BXGYConfig;
74
74
  tiers?: TieredDiscount[];
75
+ /**
76
+ * D51 — percentage of the amount PAID that a `points_earn` coupon awards as
77
+ * points. Meaningless, and ignored, on every other type.
78
+ *
79
+ * ## 🛑 Why this is not `discount.value`
80
+ *
81
+ * `discount` is read by `computeGroupCouponDiscount` to reduce the order.
82
+ * Overloading its `value` to mean "percent awarded as points" would make a
83
+ * points coupon discount the order by the same number it was supposed to
84
+ * credit — the exact overloading that `bxgy` and `tiers` are separate fields
85
+ * to avoid.
86
+ *
87
+ * `discount` stays REQUIRED on the interface because every existing coupon
88
+ * has one and widening it to optional would ripple through ~30 readers; a
89
+ * points coupon carries `{ value: 0 }`. The protection that matters is in
90
+ * the discount loop, which skips on TYPE rather than trusting that zero
91
+ * (`coupon-discount.ts`) — bad data cannot bypass a type check.
92
+ *
93
+ * The base is the post-discount amount actually paid in money, which is
94
+ * `POINTS_EARN_PERCENT`'s existing rule; this field exists so a campaign can
95
+ * raise it (the festival double event) without editing a constant.
96
+ */
97
+ pointsPercent?: number;
75
98
  usage: UsageConfig;
76
99
  validity: ValidityConfig;
77
100
  restrictions: RestrictionsConfig;
@@ -143,6 +166,7 @@ export declare const COUPON_FIELDS: {
143
166
  readonly FIXED: CouponType;
144
167
  readonly FREE_SHIPPING: CouponType;
145
168
  readonly BUY_X_GET_Y: CouponType;
169
+ readonly POINTS_EARN: CouponType;
146
170
  };
147
171
  readonly SCOPE_VALUES: {
148
172
  readonly ADMIN: "admin";
@@ -48,6 +48,7 @@ export const COUPON_FIELDS = {
48
48
  FIXED: "fixed",
49
49
  FREE_SHIPPING: "free_shipping",
50
50
  BUY_X_GET_Y: "buy_x_get_y",
51
+ POINTS_EARN: "points_earn",
51
52
  },
52
53
  SCOPE_VALUES: {
53
54
  ADMIN: "admin",
@@ -59,6 +60,9 @@ export const COUPON_TYPE_LABELS = {
59
60
  fixed: "Fixed Amount Discount",
60
61
  free_shipping: "Free Shipping",
61
62
  buy_x_get_y: "Buy X Get Y",
63
+ // Named for what the buyer gets, not for the mechanism. "Points earn" is
64
+ // our word for it; "Points back" is what appears on their balance.
65
+ points_earn: "Points Back",
62
66
  };
63
67
  export const DEFAULT_COUPON_DATA = {
64
68
  usage: { currentUsage: 0 },
@@ -1,4 +1,22 @@
1
- export type CouponType = "percentage" | "fixed" | "free_shipping" | "buy_x_get_y";
1
+ export type CouponType = "percentage" | "fixed" | "free_shipping" | "buy_x_get_y"
2
+ /**
3
+ * D51 — a coupon that awards POINTS rather than discounting the order.
4
+ *
5
+ * 🛑 It carries `pointsPercent`, not a discount value, and it must never
6
+ * reach the discount arithmetic: a `points_earn` coupon with a `discount`
7
+ * field read by `computeGroupCouponDiscount` would silently discount the
8
+ * order as well as award points.
9
+ *
10
+ * It exists because `RIPLI05` is a PERMANENT, site-wide coupon, and
11
+ * `detectCouponConflict` permits exactly one admin coupon site-wide — so
12
+ * putting it in the admin slot would make every other platform coupon
13
+ * unusable for as long as it exists. It gets its own stacking bucket.
14
+ *
15
+ * Adding it here is a compile error at `COUPON_TYPE_LABELS`, which is a
16
+ * `Record<CouponType, string>` — that is the point of declaring the union
17
+ * first.
18
+ */
19
+ | "points_earn";
2
20
  export type CouponScope = "admin" | "seller";
3
21
  export interface CouponItem {
4
22
  id: string;
@@ -52,6 +52,20 @@ declare class ReviewRepository extends BaseRepository<ReviewDocument> {
52
52
  findApprovedByStore(storeId: string, limit?: number): Promise<ReviewDocument[]>;
53
53
  findByUser(userId: string): Promise<ReviewDocument[]>;
54
54
  findApprovedByUser(userId: string): Promise<ReviewDocument[]>;
55
+ /**
56
+ * How many reviews this account has WRITTEN.
57
+ *
58
+ * Deliberately every status and both reviewer roles — it counts the same set
59
+ * `GET /api/user/reviews` lists by default (`findByUser`), so the number in
60
+ * the sidebar and the rows on the page it links to agree by construction. A
61
+ * count that quietly excluded pending reviews would read as the author's
62
+ * work having vanished.
63
+ *
64
+ * An aggregation, not `findByUser(...).length`: that sibling downloads every
65
+ * review the account has ever written to learn how many there are, and the
66
+ * caller here runs on every session profile fetch.
67
+ */
68
+ countByUser(userId: string): Promise<number>;
55
69
  findPending(): Promise<ReviewDocument[]>;
56
70
  findByStatus(status: ReviewStatus): Promise<ReviewDocument[]>;
57
71
  /**
@@ -175,6 +175,22 @@ class ReviewRepository extends BaseRepository {
175
175
  .get();
176
176
  return snapshot.docs.map((doc) => this.mapDoc(doc));
177
177
  }
178
+ /**
179
+ * How many reviews this account has WRITTEN.
180
+ *
181
+ * Deliberately every status and both reviewer roles — it counts the same set
182
+ * `GET /api/user/reviews` lists by default (`findByUser`), so the number in
183
+ * the sidebar and the rows on the page it links to agree by construction. A
184
+ * count that quietly excluded pending reviews would read as the author's
185
+ * work having vanished.
186
+ *
187
+ * An aggregation, not `findByUser(...).length`: that sibling downloads every
188
+ * review the account has ever written to learn how many there are, and the
189
+ * caller here runs on every session profile fetch.
190
+ */
191
+ async countByUser(userId) {
192
+ return getFirestoreCount(this.getCollection().where(REVIEW_FIELDS.USER_ID, "==", userId));
193
+ }
178
194
  async findPending() {
179
195
  return this.findBy(REVIEW_FIELDS.STATUS, "pending");
180
196
  }
@@ -4,7 +4,7 @@ import { formatCurrency } from "../../../utils/number.formatter.js";
4
4
  const CLS_OUTLINE_BTN = "appkit-button appkit-button--outline appkit-button--md flex w-full items-center gap-[var(--appkit-space-2)]";
5
5
  import Link from "next/link.js";
6
6
  import { Shield, Phone, Wallet, Mail, AlertOctagon, Flag, Eye, Users, Calendar, ExternalLink, FileText, MessageSquare, Link2, } from "lucide-react";
7
- import { Alert, Anchor, Badge, Breadcrumb, Card, CardBody, CardHeader, Container, Div, EmptyState, Grid, Heading, Main, Row, Section, Span, Stack, Text, } from "../../../ui/index.js";
7
+ import { Alert, Anchor, Badge, Breadcrumb, Card, CardBody, CardHeader, Container, Disclaimer, Div, EmptyState, Grid, Heading, Main, Row, Section, Span, Stack, Text, } from "../../../ui/index.js";
8
8
  import { MediaImage } from "../../media/MediaImage.js";
9
9
  import { SCAM_PLATFORM_LABELS, SCAMMER_STATUS_LABELS, SOCIAL_PLATFORM_LABELS, CONTEST_TYPE_LABELS, } from "../schemas/firestore.js";
10
10
  import { SCAM_TYPE_LABELS, getScamType } from "../constants/scam-types.js";
@@ -32,7 +32,7 @@ function statusVariant(status) {
32
32
  }
33
33
  // ─── Sub-components ───────────────────────────────────────────────────────────
34
34
  function ScammerHeaderCard({ scammer }) {
35
- return (_jsx(Card, { variant: "elevated", padding: "lg", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { justify: "between", gap: "md", align: "start", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: scammer.displayNames[0] }), scammer.displayNames.length > 1 && (_jsxs(Text, { variant: "secondary", size: "sm", children: ["Also known as: ", scammer.displayNames.slice(1).join(", ")] }))] }), _jsx(Badge, { variant: statusVariant(scammer.status), children: SCAMMER_STATUS_LABELS[scammer.status] ?? scammer.status })] }), _jsxs(Row, { gap: "xs", wrap: true, children: [_jsx(Badge, { variant: "warning", children: SCAM_TYPE_LABELS[scammer.scamType] ?? scammer.scamType }), _jsxs(Badge, { variant: "default", children: ["via ", SCAM_PLATFORM_LABELS[scammer.scamPlatform] ?? scammer.scamPlatform] }), scammer.tags.includes("repeat_offender") && (_jsx(Badge, { variant: "danger", children: "Repeat Offender" }))] }), _jsxs(Row, { gap: "md", wrap: true, children: [_jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Eye, { className: "h-4 w-4" }), scammer.views, " views"] }), _jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Users, { className: "h-4 w-4" }), scammer.incidentCount + 1, " victim", scammer.incidentCount !== 0 ? "s" : "", " reported"] }), _jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Calendar, { className: "h-4 w-4" }), "Reported ", formatDate(scammer.createdAt)] }), scammer.amountLost ? (_jsxs(Text, { className: "text-[color:var(--appkit-color-danger,theme(colors.red.600))]", size: "sm", weight: "medium", children: [formatCurrency(scammer.amountLost), " lost (primary incident)"] })) : null] })] }) }));
35
+ return (_jsx(Card, { variant: "elevated", padding: "lg", children: _jsxs(Stack, { gap: "md", children: [_jsx(Disclaimer, { id: "scam-registry" }), _jsxs(Row, { justify: "between", gap: "md", align: "start", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: scammer.displayNames[0] }), scammer.displayNames.length > 1 && (_jsxs(Text, { variant: "secondary", size: "sm", children: ["Also known as: ", scammer.displayNames.slice(1).join(", ")] }))] }), _jsx(Badge, { variant: statusVariant(scammer.status), children: SCAMMER_STATUS_LABELS[scammer.status] ?? scammer.status })] }), _jsxs(Row, { gap: "xs", wrap: true, children: [_jsx(Badge, { variant: "warning", children: SCAM_TYPE_LABELS[scammer.scamType] ?? scammer.scamType }), _jsxs(Badge, { variant: "default", children: ["via ", SCAM_PLATFORM_LABELS[scammer.scamPlatform] ?? scammer.scamPlatform] }), scammer.tags.includes("repeat_offender") && (_jsx(Badge, { variant: "danger", children: "Repeat Offender" }))] }), _jsxs(Row, { gap: "md", wrap: true, children: [_jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Eye, { className: "h-4 w-4" }), scammer.views, " views"] }), _jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Users, { className: "h-4 w-4" }), scammer.incidentCount + 1, " victim", scammer.incidentCount !== 0 ? "s" : "", " reported"] }), _jsxs(Text, { variant: "secondary", layout: "flex", gap: "1.5", size: "sm", children: [_jsx(Calendar, { className: "h-4 w-4" }), "Reported ", formatDate(scammer.createdAt)] }), scammer.amountLost ? (_jsxs(Text, { className: "text-[color:var(--appkit-color-danger,theme(colors.red.600))]", size: "sm", weight: "medium", children: [formatCurrency(scammer.amountLost), " lost (primary incident)"] })) : null] })] }) }));
36
36
  }
37
37
  function ScammerIncidentsSection({ incidents }) {
38
38
  return (_jsxs(Stack, { gap: "sm", children: [_jsx(Row, { justify: "between", align: "center", children: _jsxs(Heading, { level: 2, size: "base", weight: "semibold", children: ["Additional Incidents", incidents.length > 0 && ` (${incidents.length})`] }) }), incidents.length === 0 ? (_jsx(EmptyState, { icon: _jsx(FileText, { className: "h-8 w-8" }), title: "No additional incidents yet", description: "Other victims' verified reports linked to this profile will appear here." })) : (_jsx(Stack, { gap: "sm", children: incidents.map((inc) => (_jsx(Card, { variant: "outlined", padding: "md", children: _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", align: "start", gap: "sm", wrap: true, children: [_jsxs(Row, { gap: "xs", wrap: true, children: [_jsx(Badge, { variant: "warning", children: SCAM_TYPE_LABELS[inc.scamType] ?? inc.scamType }), _jsxs(Badge, { variant: "default", children: ["via ", SCAM_PLATFORM_LABELS[inc.scamPlatform] ?? inc.scamPlatform] })] }), _jsx(Text, { variant: "secondary", size: "xs", children: formatDate(inc.createdAt) })] }), inc.itemInvolved && (_jsxs(Text, { variant: "secondary", size: "xs", children: ["Item: ", inc.itemInvolved] })), inc.amountLost ? (_jsxs(Text, { className: "text-[color:var(--appkit-color-danger,theme(colors.red.600))]", size: "xs", weight: "medium", children: [formatCurrency(inc.amountLost), " lost"] })) : null, _jsx(Text, { variant: "secondary", className: "leading-relaxed", size: "sm", children: inc.description.length > 200
@@ -7,7 +7,7 @@ const CLS_ICON_SM = "h-3 w-3 shrink-0";
7
7
  const CLS_ROW_CHEVRON = "h-4 w-4 shrink-0 transition group-hover:text-error text-[var(--appkit-color-text-faint)]";
8
8
  const CLS_PILL_LINK = "inline-flex items-center gap-[var(--appkit-space-1)] rounded-full bg-error-surface dark:bg-error-surface px-[var(--appkit-space-2-5)] py-[var(--appkit-space-0-5)] text-[length:var(--appkit-text-xs)] font-medium text-error dark:text-error hover:bg-error-surface transition-colors";
9
9
  import { Shield, Phone, Wallet, Mail, ChevronRight, Search } from "lucide-react";
10
- import { Button, Container, Div, Form, Heading, Main, Section, Select, Text, Grid, Stack, Row, Card, Badge, Alert, EmptyState, Input, } from "../../../ui/index.js";
10
+ import { Button, Container, Disclaimer, Div, Form, Heading, Main, Section, Select, Text, Grid, Stack, Row, Card, Badge, Alert, EmptyState, Input, } from "../../../ui/index.js";
11
11
  import { listVerifiedScammers } from "../actions/scam-actions.js";
12
12
  import { SCAM_PLATFORM_LABELS } from "../schemas/firestore.js";
13
13
  import { SCAM_TYPES, SCAM_TYPE_LABELS } from "../constants/scam-types.js";
@@ -61,7 +61,7 @@ export async function ScamRegistryView({ searchParams = {} }) {
61
61
  const qs = p.toString();
62
62
  return `/scams${qs ? `?${qs}` : ""}`;
63
63
  }
64
- return (_jsxs(Main, { children: [_jsx(Div, { className: "border-b appkit-alert--warning", rounded: "none", children: _jsx(Container, { padding: "y-xs", size: "xl", className: "", children: _jsxs(Alert, { variant: "warning", compact: true, children: ["All profiles on this page have been verified by our moderation team. If you recognise a scammer not listed here,", " ", _jsx(Link, { href: reportHref, className: "font-medium underline hover:no-underline", children: "report them" }), "."] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "xl", children: [_jsxs(Row, { justify: "between", gap: "md", align: "end", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "semibold", size: "3xl", children: "Scam Registry" }), _jsx(Text, { variant: "secondary", size: "sm", children: "Verified scammers active in India's collectibles community. Search by name, phone, or UPI." })] }), _jsxs(Link, { href: reportHref, className: "appkit-button appkit-button--danger appkit-button--md shrink-0", children: [_jsx(Shield, { className: "h-4 w-4" }), "Report a Scammer"] })] }), _jsx(Form, { method: "GET", children: _jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Div, { className: "flex-1 min-w-48", children: _jsx(Input, { type: "search", name: "q", defaultValue: query, placeholder: "Search name, phone, UPI ID, or email\u2026", icon: _jsx(Search, { className: "h-4 w-4" }) }) }), _jsx(Select, { name: "scamType", defaultValue: scamType, options: SCAM_TYPES.map((t) => ({ value: t.id, label: t.label })), placeholder: "All scam types" }), _jsx(Select, { name: "sort", defaultValue: sort, options: SORT_OPTIONS.map((o) => ({ value: o.value, label: o.label })) }), _jsx(Button, { type: "submit", variant: "primary", size: "sm", children: "Search" }), (query || scamType || sort !== "-createdAt") && (_jsx(Link, { href: ROUTES.PUBLIC.SCAMS, className: "rounded-lg border border-[var(--appkit-color-border)] px-[var(--appkit-space-4)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text-muted)] hover:bg-surface-hover transition-colors", children: "Clear" }))] }) }), scamType && SCAM_TYPE_LABELS[scamType] && (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "secondary", size: "xs", children: "Filtering by:" }), _jsxs(Link, { href: buildHref({ scamType: "" }), className: CLS_PILL_LINK, children: [SCAM_TYPE_LABELS[scamType], _jsx(Span, { "aria-hidden": "true", children: "\u00D7" })] })] })), result.items.length === 0 ? (_jsx(EmptyState, { icon: _jsx(Shield, { className: "h-12 w-12" }), title: query || scamType
64
+ return (_jsxs(Main, { children: [_jsx(Div, { className: "border-b appkit-alert--warning", rounded: "none", children: _jsx(Container, { padding: "y-xs", size: "xl", className: "", children: _jsxs(Alert, { variant: "warning", compact: true, children: ["All profiles on this page have been verified by our moderation team. If you recognise a scammer not listed here,", " ", _jsx(Link, { href: reportHref, className: "font-medium underline hover:no-underline", children: "report them" }), "."] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "xl", children: [_jsxs(Row, { justify: "between", gap: "md", align: "end", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "semibold", size: "3xl", children: "Scam Registry" }), _jsx(Text, { variant: "secondary", size: "sm", children: "Reports of scams in India's collectibles community, submitted by buyers and sellers. Search by name, phone, or UPI." })] }), _jsxs(Link, { href: reportHref, className: "appkit-button appkit-button--danger appkit-button--md shrink-0", children: [_jsx(Shield, { className: "h-4 w-4" }), "Report a Scammer"] })] }), _jsx(Disclaimer, { id: "scam-registry" }), _jsx(Form, { method: "GET", children: _jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Div, { className: "flex-1 min-w-48", children: _jsx(Input, { type: "search", name: "q", defaultValue: query, placeholder: "Search name, phone, UPI ID, or email\u2026", icon: _jsx(Search, { className: "h-4 w-4" }) }) }), _jsx(Select, { name: "scamType", defaultValue: scamType, options: SCAM_TYPES.map((t) => ({ value: t.id, label: t.label })), placeholder: "All scam types" }), _jsx(Select, { name: "sort", defaultValue: sort, options: SORT_OPTIONS.map((o) => ({ value: o.value, label: o.label })) }), _jsx(Button, { type: "submit", variant: "primary", size: "sm", children: "Search" }), (query || scamType || sort !== "-createdAt") && (_jsx(Link, { href: ROUTES.PUBLIC.SCAMS, className: "rounded-lg border border-[var(--appkit-color-border)] px-[var(--appkit-space-4)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text-muted)] hover:bg-surface-hover transition-colors", children: "Clear" }))] }) }), scamType && SCAM_TYPE_LABELS[scamType] && (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "secondary", size: "xs", children: "Filtering by:" }), _jsxs(Link, { href: buildHref({ scamType: "" }), className: CLS_PILL_LINK, children: [SCAM_TYPE_LABELS[scamType], _jsx(Span, { "aria-hidden": "true", children: "\u00D7" })] })] })), result.items.length === 0 ? (_jsx(EmptyState, { icon: _jsx(Shield, { className: "h-12 w-12" }), title: query || scamType
65
65
  ? "No verified scammers matched your filters"
66
66
  : "No verified scammers in the registry yet", description: query || scamType
67
67
  ? "Try a different search or clear your filters."
@@ -142,7 +142,8 @@ class ScammerRepository extends BaseRepository {
142
142
  reason: ctx?.reason,
143
143
  note: ctx?.note,
144
144
  // A scammer profile is built entirely from identifying details, and
145
- // `encryptPiiFields` never descends into arrays.
145
+ // `encryptPiiFields` covers a field only where it is NAMED. It CAN
146
+ // reach into an array via `array[].key`, but a bare key does not.
146
147
  piiFields: SCAMMER_HISTORY_PII_FIELDS,
147
148
  });
148
149
  const data = prepareForFirestore(withEntry ?? { ...input, updatedAt: new Date() });
@@ -403,6 +403,7 @@ export declare const SCAMMER_TRACKED_FIELDS: readonly ["status", "verifiedBy", "
403
403
  /**
404
404
  * PII on this document, for `withHistory`'s scrub. A scammer profile is built
405
405
  * ENTIRELY out of identifying details, so this list is long on purpose —
406
- * `encryptPiiFields` never descends into arrays, and history is an array.
406
+ * `encryptPiiFields` covers only NAMED paths, and nobody is going to declare
407
+ * `statusHistory[].changes.<key>` for every field that might land there.
407
408
  */
408
409
  export declare const SCAMMER_HISTORY_PII_FIELDS: readonly ["name", "displayName", "email", "phone", "phoneNumber", "upiId", "bankAccount", "accountNumber", "reporterEmail", "reporterName"];
@@ -248,7 +248,8 @@ export const SCAMMER_TRACKED_FIELDS = [
248
248
  /**
249
249
  * PII on this document, for `withHistory`'s scrub. A scammer profile is built
250
250
  * ENTIRELY out of identifying details, so this list is long on purpose —
251
- * `encryptPiiFields` never descends into arrays, and history is an array.
251
+ * `encryptPiiFields` covers only NAMED paths, and nobody is going to declare
252
+ * `statusHistory[].changes.<key>` for every field that might land there.
252
253
  */
253
254
  export const SCAMMER_HISTORY_PII_FIELDS = [
254
255
  "name",
@@ -103,7 +103,7 @@ export const CONSOLIDATED_TAB_SURFACES = [
103
103
  tab: "navigation",
104
104
  portal: "admin",
105
105
  sectionPath: "Admin › System › Permissions Toggles",
106
- requiredPermission: "settings:write",
106
+ requiredPermission: "admin:settings:write",
107
107
  },
108
108
  ];
109
109
  export function deriveConsolidatedTabEntries(hrefs) {
@@ -7,6 +7,9 @@
7
7
  import { serverLogger } from "../../../monitoring/index.js";
8
8
  import { offerRepository } from "../repository/offer.repository.js";
9
9
  import { productRepository } from "../../products/repository/products.repository.js";
10
+ import { categoriesRepository } from "../../categories/repository/categories.repository.js";
11
+ import { resolveParcel } from "../../../_internal/shared/features/shipping/parcel.js";
12
+ import { checkDestinations, assertAllServiceable, } from "../../../_internal/server/features/shipping/book-split.js";
10
13
  import { ProductStatusValues } from "../../products/schemas/index.js";
11
14
  import { sendNotification } from "../../admin/actions/notification-actions.js";
12
15
  import { userRepository } from "../../auth/repository/user.repository.js";
@@ -184,6 +187,59 @@ export async function respondToOffer(userId, input) {
184
187
  throw new ValidationError(ERROR_MESSAGES.OFFER.EXPIRED);
185
188
  let updated;
186
189
  if (action === "accept") {
190
+ /*
191
+ * ── S5a: a coordinated offer must be SHIPPABLE before it is binding ──
192
+ *
193
+ * Accepting locks a price and starts the buyer's checkout deadline, so it
194
+ * is the last moment at which "the courier cannot reach one of these
195
+ * addresses" costs nobody anything. After it, the coordinator has paid
196
+ * and the only remedies left are a refund and an apology.
197
+ *
198
+ * 🛑 Deliberately NOT at booking time, which is the obvious place and the
199
+ * wrong one: by then the money is taken, and a four-destination order
200
+ * that fails on the fourth has three parcels the carrier already accepted
201
+ * and no rollback. `assertAllServiceable` still guards the booking path —
202
+ * this is the check that keeps it from ever being reached in that state.
203
+ *
204
+ * 🛑 Costs NOTHING on an ordinary offer. `coordination` is absent on
205
+ * every non-coordinated one, so this whole block is skipped — a check
206
+ * that charges every seller for a feature most never use is how Rule #6's
207
+ * round-trip budget gets spent by accident.
208
+ *
209
+ * 🛑 The weight comes from `resolveParcel`, NOT from a literal. That
210
+ * module's whole argument is that an item weight systematically
211
+ * under-estimates a packed box (a bey is ~30 g loose and ~300 g boxed),
212
+ * and a hard-coded `1` here would be a fourth, worse tier beside the
213
+ * three it defines. The shipment tier is deliberately absent — nothing is
214
+ * packed yet at accept time, which is exactly the case tier two and three
215
+ * exist for.
216
+ *
217
+ * 🛑 **No resolvable weight SKIPS the check** rather than guessing one.
218
+ * The carrier is being asked "can you reach this pincode with a parcel of
219
+ * this size", so an invented weight asks a question about a parcel that
220
+ * does not exist and may refuse a destination that is perfectly
221
+ * reachable. Not checking is honest; the booking path still has
222
+ * `assertAllServiceable`, and a listing with no weight at any tier has a
223
+ * data problem this is not the place to report.
224
+ */
225
+ const members = offer.coordination?.members ?? [];
226
+ if (members.length > 0) {
227
+ const offerProduct = await productRepository.findById(offer.productId);
228
+ /*
229
+ * 🛑 `categorySlugs[0]` is the LEAF, and `findById` is the right lookup
230
+ * for it. Products carry the full ancestor chain `[leaf, …, root]` and
231
+ * categories are pure slugs (`id === slug`), so this is one get rather
232
+ * than the `where("slug","==")` query `findBySlugAndType` would run —
233
+ * and the leaf is the tier whose packed default is actually about this
234
+ * kind of item. A root's default would be the average of the catalogue.
235
+ */
236
+ const leafSlug = offerProduct?.categorySlugs?.[0];
237
+ const leaf = leafSlug ? await categoriesRepository.findById(leafSlug) : null;
238
+ const parcel = resolveParcel(null, offerProduct, leaf?.productDefaults ?? null);
239
+ if (parcel) {
240
+ assertAllServiceable(await checkDestinations(members, parcel.weightG / 1000));
241
+ }
242
+ }
187
243
  updated = await offerRepository.accept(offerId, offer.offerAmount, sellerNote, new Date(Date.now() + OFFER_CHECKOUT_WINDOW_MS));
188
244
  }
189
245
  else if (action === "decline") {
@@ -181,7 +181,7 @@ export declare function listSellerPayouts(userId: string, params?: {
181
181
  page?: number;
182
182
  pageSize?: number;
183
183
  }): Promise<{
184
- items: import("../../payments").PayoutDocument[];
184
+ items: import("../../payments").StorePayoutDocument[];
185
185
  total: number;
186
186
  page: number;
187
187
  pageSize: number;
@@ -28,7 +28,7 @@ import { couponsRepository } from "../../promotions/repository/coupons.repositor
28
28
  import { generateStoreSlug } from "../../stores/schemas/firestore.js";
29
29
  import { siteSettingsRepository } from "../../admin/repository/site-settings.repository.js";
30
30
  import { computePayoutDeduction } from "../../../_internal/shared/fees/calculator.js";
31
- import { ordersTaxableValue, ordersShippingReimbursement, } from "../../../_internal/shared/checkout/order-math.js";
31
+ import { ordersTaxableValue, ordersShippingReimbursement, ordersPointsBorneByStore, } from "../../../_internal/shared/checkout/order-math.js";
32
32
  import { getDefaultCurrency } from "../../../core/baseline-resolver.js";
33
33
  import { finalizeStagedMediaUrl, finalizeStagedMediaField, finalizeStagedMediaArray, } from "../../media/finalize.js";
34
34
  import { StoreStatusValues } from "../../stores/schemas/firestore.js";
@@ -249,7 +249,19 @@ async function computeSellerEarnings(sellerId) {
249
249
  * alone.
250
250
  */
251
251
  const shippingReimbursement = ordersShippingReimbursement(eligibleOrders);
252
- const deduction = computePayoutDeduction(grossAmount, siteSettings.commissions, shippingReimbursement);
252
+ /*
253
+ * D46/D47 — the points programme, which the STORE funds at both ends
254
+ * (decisions 3 and 17): points issued on these orders plus points spent on
255
+ * them. Deducted outside the commission and gateway bases, for the inverse
256
+ * of postage's reason — the seller agreed to fund a discount, not to pay us a
257
+ * commission on the discount they funded.
258
+ *
259
+ * 🛑 Passed at all FOUR call sites, exactly like `shippingReimbursement`
260
+ * above. `ordersPointsFunded` existed with zero consumers before this, which
261
+ * meant the platform had silently been funding the earn.
262
+ */
263
+ const pointsFunded = ordersPointsBorneByStore(eligibleOrders);
264
+ const deduction = computePayoutDeduction(grossAmount, siteSettings.commissions, shippingReimbursement, pointsFunded);
253
265
  return {
254
266
  eligibleOrders,
255
267
  grossAmount,
@@ -257,6 +269,22 @@ async function computeSellerEarnings(sellerId) {
257
269
  gatewayFee: deduction.gatewayFee,
258
270
  gstAmount: deduction.gstOnFee,
259
271
  netAmount: deduction.netAmount,
272
+ /*
273
+ * Surfaced so a seller can see WHY a payout is short of
274
+ * `gross − fees`. Two terms now move `netAmount` without appearing in
275
+ * `totalDeduction` — postage up, points down — and a net figure that
276
+ * cannot be reconstructed from the figures beside it reads as an error in
277
+ * our arithmetic rather than as the two things the seller agreed to.
278
+ *
279
+ * 🛑 Returned rather than written to `PayoutDocument`, matching
280
+ * `shippingReimbursement`, which is also not on that schema. One of these
281
+ * should probably be persisted eventually — a settled payout cannot be
282
+ * re-explained from a preview — but adding a document field with no reader
283
+ * is the pattern this very function just finished closing, so it waits for
284
+ * the admin surface that would read it.
285
+ */
286
+ shippingReimbursement: deduction.shippingReimbursement,
287
+ pointsFunded: deduction.pointsFunded,
260
288
  productCount: products.length,
261
289
  commissions: siteSettings.commissions,
262
290
  };
@@ -271,6 +299,8 @@ export async function requestPayout(userId, userName, userEmail, input) {
271
299
  if (earnings.netAmount <= 0 || earnings.eligibleOrders.length === 0)
272
300
  throw new ValidationError("No eligible earnings available for payout.");
273
301
  const payout = await payoutRepository.createPayout({
302
+ /* A seller requesting their own earnings — a liability settlement. */
303
+ payeeType: "store",
274
304
  storeId: userId,
275
305
  sellerName: userName,
276
306
  sellerEmail: userEmail,
@@ -359,8 +389,12 @@ export async function bulkSellerOrder(userId, userRole, userDisplayName, userEma
359
389
  * scheduled job pay differently for the same orders. */
360
390
  const grossAmount = ordersTaxableValue(eligible);
361
391
  const bulkSiteSettings = await siteSettingsRepository.getSingleton();
362
- const bulkDeduction = computePayoutDeduction(grossAmount, bulkSiteSettings.commissions, ordersShippingReimbursement(eligible));
392
+ const bulkDeduction = computePayoutDeduction(grossAmount, bulkSiteSettings.commissions, ordersShippingReimbursement(eligible),
393
+ // The store-funded points, both ends — see the preview path above.
394
+ ordersPointsBorneByStore(eligible));
363
395
  const payoutDoc = await payoutRepository.createPayout({
396
+ /* A seller requesting their own earnings — a liability settlement. */
397
+ payeeType: "store",
364
398
  storeId: userId,
365
399
  sellerName: userDisplayName,
366
400
  sellerEmail: userEmail,
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ export declare function DispatchForm({ orderId,
3
+ /** Already dispatched? Then there is nothing to book and nothing to record. */
4
+ trackingNumber,
5
+ /** Set by `bookShipment`; a booked parcel must not be re-booked. */
6
+ platformBooked, onDispatched, }: {
7
+ orderId: string;
8
+ trackingNumber?: string;
9
+ platformBooked?: boolean;
10
+ onDispatched: () => void;
11
+ }): React.JSX.Element;
@@ -0,0 +1,190 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /*
4
+ * WHY: Bug 0e — a seller could not express "book this through us". The write
5
+ * shape said `method: z.literal("custom")`, so there was no option to
6
+ * offer; `platformBookedShipment`, which `order-math.ts` gates shipping
7
+ * reimbursement on, had ZERO writers.
8
+ *
9
+ * The schema now carries a discriminated union and the server does the
10
+ * booking. This is the control that reaches it.
11
+ *
12
+ * WHAT: One dispatch panel with two branches — post it yourself, or book a
13
+ * pickup on the platform's carrier account.
14
+ *
15
+ * EXPORTS: DispatchForm
16
+ *
17
+ * @tag domain:seller,orders,shipping
18
+ * @tag layer:component
19
+ * @tag pattern:form
20
+ * @tag access:client
21
+ * @tag consumers:SellerOrderDetailPanel
22
+ * @tag sideEffects:network
23
+ */
24
+ import React, { useState } from "react";
25
+ import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
26
+ import { SELLER_ENDPOINTS } from "../../../constants/api-endpoints.js";
27
+ import { apiClient, ApiClientError } from "../../../http/index.js";
28
+ import { useApiMutation } from "../../../client/api/useApiMutation.js";
29
+ import { useQuery } from "@tanstack/react-query";
30
+ import { normalizeError } from "../../../errors/normalize.js";
31
+ import { toUserMessage } from "../../../errors/error-display-map.js";
32
+ import { Button } from "../../../ui/components/Button.js";
33
+ import { Div } from "../../../ui/components/Div.js";
34
+ import { Row } from "../../../ui/components/Layout.js";
35
+ import { Stack } from "../../../ui/components/Layout.js";
36
+ import { Text } from "../../../ui/components/Typography.js";
37
+ import { Form } from "../../../ui/components/Form.js";
38
+ import { FieldInput } from "../../../ui/forms/FieldInput.js";
39
+ import { FieldSelect } from "../../../ui/forms/FieldSelect.js";
40
+ import { shipOrderSchema } from "../schemas/order-forms.js";
41
+ import { applyZodIssues, rootLevelMessages } from "../../../ui/forms/apply-zod-issues.js";
42
+ /**
43
+ * Box presets, in centimetres and kilograms.
44
+ *
45
+ * 🛑 A PRESET rather than four number inputs, and that is the whole UX
46
+ * argument: a seller packing a Beyblade does not know the parcel's
47
+ * dimensions, and a carrier rejects a wrong one with an opaque error at
48
+ * pickup time rather than at booking time. Four free fields produce four
49
+ * chances to guess. "Custom" exists for the genuinely odd parcel.
50
+ */
51
+ const BOX_PRESETS = [
52
+ { id: "small", label: "Small — single top (0.3 kg)", weight: 0.3, length: 20, width: 15, height: 10 },
53
+ { id: "medium", label: "Medium — a few items (1 kg)", weight: 1, length: 30, width: 25, height: 15 },
54
+ { id: "large", label: "Large — stadium or bundle (3 kg)", weight: 3, length: 45, width: 35, height: 25 },
55
+ ];
56
+ export function DispatchForm({ orderId,
57
+ /** Already dispatched? Then there is nothing to book and nothing to record. */
58
+ trackingNumber,
59
+ /** Set by `bookShipment`; a booked parcel must not be re-booked. */
60
+ platformBooked, onDispatched, }) {
61
+ const [method, setMethod] = useState("custom");
62
+ const [carrier, setCarrier] = useState("");
63
+ const [tracking, setTracking] = useState("");
64
+ const [trackingUrl, setTrackingUrl] = useState("");
65
+ const [pickupId, setPickupId] = useState("");
66
+ const [boxId, setBoxId] = useState(BOX_PRESETS[1].id);
67
+ const [error, setError] = useState(null);
68
+ /*
69
+ * 🛑 Fetched ONLY when the platform branch is open. The custom branch is
70
+ * the common case and needs no address at all, so loading this on mount
71
+ * would be a request on every order panel open for a field most sellers
72
+ * never reach (Rule #6).
73
+ */
74
+ /*
75
+ * 🛑 `toUserMessage(code)` on failure, never the server's own `error`
76
+ * string — an unmapped code would print server internals into the panel,
77
+ * which is literally how a Node `MODULE_NOT_FOUND` with a require stack
78
+ * reached a buyer-facing modal (Root Cause #86). `ApiClientError` carries
79
+ * the stable code, so the mapping survives the move off raw `fetch`.
80
+ */
81
+ /*
82
+ * 🛑 A REF, because `setFieldError` comes from `<Form>`'s render-prop and
83
+ * therefore does not exist in component scope where the mutation is
84
+ * declared. The mutation needs a STABLE sink — passing the render-prop
85
+ * helper directly is impossible, and re-creating the mutation per render to
86
+ * close over it would reset its pending state mid-request.
87
+ *
88
+ * It is assigned inside the render-prop below, so by the time any submit
89
+ * can fire it is populated. The `?.` is not defensive decoration: the first
90
+ * render completes before `<Form>` calls its child.
91
+ */
92
+ const fieldErrorSink = React.useRef(null);
93
+ const shipMutation = useApiMutation({
94
+ /*
95
+ * 🛑 Passed so the server's own per-field `issues` land on the fields
96
+ * they name. The route parses the same `shipOrderSchema` this form does,
97
+ * so a rejection it produces that the client parse did not is real news
98
+ * — a carrier the courier does not recognise, a pickup address that
99
+ * stopped being serviceable — and collapsing that into one generic
100
+ * sentence hides which input to fix.
101
+ */
102
+ setFieldError: (field, message) => fieldErrorSink.current?.(field, message),
103
+ mutationFn: (payload) => apiClient.post(SELLER_ENDPOINTS.ORDER_SHIP(orderId), payload),
104
+ onSuccess: () => onDispatched(),
105
+ onError: (err) => {
106
+ void normalizeError(err);
107
+ setError(toUserMessage(err instanceof ApiClientError ? err.code : undefined));
108
+ },
109
+ });
110
+ /*
111
+ * 🛑 `enabled` is what keeps this request off the common path. The custom
112
+ * branch needs no address at all, so loading pickups on mount would fire a
113
+ * request on every order panel a seller opens for a field most of them
114
+ * never reach (Rule #6). `useQuery` also dedupes and caches it, which the
115
+ * hand-rolled effect could not — it refetched on every branch toggle.
116
+ */
117
+ const pickupsQuery = useQuery({
118
+ queryKey: ["store", "addresses", "pickup"],
119
+ enabled: method === "platform",
120
+ queryFn: () => apiClient.get(SELLER_ENDPOINTS.STORE_ADDRESSES),
121
+ });
122
+ const pickups = Array.isArray(pickupsQuery.data?.items)
123
+ ? pickupsQuery.data.items
124
+ : [];
125
+ /*
126
+ * 🛑 A FAILED request and an empty list must not render the same. An empty
127
+ * dropdown reads as "this store has no pickup addresses" — a fact about the
128
+ * store — when it may be a network error, and the two need different
129
+ * actions from the seller.
130
+ */
131
+ const pickupsFailed = pickupsQuery.isError;
132
+ React.useEffect(() => {
133
+ if (pickups.length === 1 && !pickupId)
134
+ setPickupId(pickups[0].id);
135
+ }, [pickups, pickupId]);
136
+ if (trackingNumber) {
137
+ return (_jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", children: "Dispatched" }), _jsx(Text, { size: "xs", color: "muted", children: platformBooked
138
+ ? `Booked through LetItRip · ${trackingNumber}`
139
+ : `Posted by you · ${trackingNumber}` })] }));
140
+ }
141
+ const submit = async (
142
+ /* The `<Form>` render-prop's own signature — `applyZodIssues` clears a
143
+ * field by passing `null`, so a `string`-only sink is not assignable. */
144
+ setFieldError, clearErrors) => {
145
+ clearErrors();
146
+ setError(null);
147
+ const box = BOX_PRESETS.find((b) => b.id === boxId) ?? BOX_PRESETS[1];
148
+ const payload = method === "platform"
149
+ ? {
150
+ method: "platform",
151
+ pickupAddressId: pickupId,
152
+ dimensions: {
153
+ weight: box.weight,
154
+ length: box.length,
155
+ width: box.width,
156
+ height: box.height,
157
+ },
158
+ }
159
+ : {
160
+ method: "custom",
161
+ shippingCarrier: carrier.trim(),
162
+ trackingNumber: tracking.trim(),
163
+ trackingUrl: trackingUrl.trim(),
164
+ };
165
+ /*
166
+ * Parsed against the SAME schema the route and the action use, so the
167
+ * branch's required fields are stated once. `applyZodIssues` can only
168
+ * attach path-bearing issues, so root-level refinements are surfaced
169
+ * separately or a refused save shows nothing at all.
170
+ */
171
+ const parsed = shipOrderSchema.safeParse(payload);
172
+ if (!parsed.success) {
173
+ applyZodIssues(parsed.error.issues, setFieldError);
174
+ const root = rootLevelMessages(parsed.error.issues);
175
+ if (root.length > 0)
176
+ setError(root.join(" "));
177
+ return;
178
+ }
179
+ shipMutation.mutate(parsed.data);
180
+ };
181
+ return (_jsxs(Stack, { gap: "3", children: [_jsx(Text, { size: "sm", weight: "medium", children: "Dispatch" }), _jsxs(Row, { gap: "sm", children: [_jsx(Button, { size: "sm", variant: method === "custom" ? "primary" : "outline", "aria-pressed": method === "custom", onClick: () => setMethod("custom"), children: "I posted it" }), _jsx(Button, { size: "sm", variant: method === "platform" ? "primary" : "outline", "aria-pressed": method === "platform", onClick: () => setMethod("platform"), children: "Book through LetItRip" })] }), _jsx(Form, { onSubmit: (e) => e.preventDefault(), children: ({ setFieldError, clearErrors }) => {
182
+ fieldErrorSink.current = setFieldError;
183
+ return (_jsxs(Stack, { gap: "3", children: [method === "custom" ? (_jsxs(_Fragment, { children: [_jsx(FieldInput, { name: "shippingCarrier", label: "Carrier", required: true, value: carrier, onChange: setCarrier }), _jsx(FieldInput, { name: "trackingNumber", label: "Tracking number", required: true, value: tracking, onChange: setTracking }), _jsx(FieldInput, { name: "trackingUrl", label: "Tracking URL", required: true, type: "url", value: trackingUrl, onChange: setTrackingUrl })] })) : (_jsxs(_Fragment, { children: [pickupsFailed ? (_jsx(Text, { size: "xs", color: "error", role: "alert", children: "Could not load your pickup addresses. Reopen this panel to try again." })) : pickups.length === 0 ? (_jsx(Text, { size: "xs", color: "muted", children: "Loading your pickup addresses\u2026" })) : (_jsx(FieldSelect, { name: "pickupAddressId", label: "Collect from", required: true, value: pickupId, onChange: setPickupId, options: pickups.map((p) => ({
184
+ value: p.id,
185
+ label: [p.label, p.city, p.postalCode].filter(Boolean).join(" · ") || p.id,
186
+ })) })), _jsx(FieldSelect, { name: "box", label: "Parcel size", required: true, value: boxId, onChange: setBoxId, options: BOX_PRESETS.map((b) => ({ value: b.id, label: b.label })) }), _jsx(Text, { size: "xs", color: "muted", children: "The courier is booked on the platform's account and the tracking id comes back from them \u2014 you do not enter one." })] })), error && (_jsx(Div, { textSize: "xs", className: "border border-error/20", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "lg", role: "alert", children: error })), _jsx(Button, { type: "submit", action: method === "platform"
187
+ ? ACTIONS.STORE["dispatch-platform"]
188
+ : ACTIONS.STORE["dispatch-custom"], isLoading: shipMutation.isPending, onClick: () => void submit(setFieldError, clearErrors) })] }));
189
+ } })] }));
190
+ }