@mohasinac/appkit 4.10.0 → 4.11.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 (319) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +4 -1
  3. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +1 -1
  4. package/dist/_internal/client/features/lottery/LotteryPullForm.js +2 -2
  5. package/dist/_internal/server/features/admin/daily-digest-actions.d.ts +18 -0
  6. package/dist/_internal/server/features/admin/daily-digest-actions.js +37 -0
  7. package/dist/_internal/server/features/audit-log/actions.d.ts +25 -0
  8. package/dist/_internal/server/features/audit-log/actions.js +38 -0
  9. package/dist/_internal/server/features/brands/actions.js +0 -2
  10. package/dist/_internal/server/features/brands/og.d.ts +4 -1
  11. package/dist/_internal/server/features/brands/og.js +1 -1
  12. package/dist/_internal/server/features/grouped/data.d.ts +4 -0
  13. package/dist/_internal/server/features/grouped/data.js +24 -0
  14. package/dist/_internal/server/features/grouped/index.d.ts +1 -1
  15. package/dist/_internal/server/features/grouped/index.js +1 -1
  16. package/dist/_internal/server/features/orders/actions.js +9 -0
  17. package/dist/_internal/server/features/orders/adapters.js +25 -0
  18. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  19. package/dist/_internal/server/functions/scheduled.js +17 -1
  20. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +40 -0
  21. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +164 -0
  22. package/dist/_internal/server/jobs/core/hardBanCascade.js +11 -0
  23. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -0
  24. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
  25. package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +12 -0
  26. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +85 -0
  27. package/dist/_internal/server/jobs/core/whatsappNotify.js +16 -0
  28. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.d.ts +2 -0
  29. package/dist/_internal/server/jobs/handlers/dailyStatusDigest.js +4 -0
  30. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  31. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  32. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +2 -0
  33. package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +2 -0
  34. package/dist/_internal/server/notifications/channel-health.d.ts +27 -0
  35. package/dist/_internal/server/notifications/channel-health.js +101 -0
  36. package/dist/_internal/shared/features/brands/schema.d.ts +0 -6
  37. package/dist/_internal/shared/features/brands/schema.js +0 -1
  38. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +7 -0
  39. package/dist/_internal/shared/features/categories/bundle-schemas.js +3 -0
  40. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  41. package/dist/client.d.ts +21 -6
  42. package/dist/client.js +13 -3
  43. package/dist/constants/api-endpoints.d.ts +6 -9
  44. package/dist/constants/api-endpoints.js +2 -3
  45. package/dist/contracts/client-auth.d.ts +3 -7
  46. package/dist/contracts/email.d.ts +1 -0
  47. package/dist/features/account/components/AddressForm.js +24 -2
  48. package/dist/features/account/components/BecomeSellerView.d.ts +1 -2
  49. package/dist/features/account/components/BecomeSellerView.js +1 -1
  50. package/dist/features/account/components/NotificationBell.js +1 -1
  51. package/dist/features/account/components/UserBidsView.d.ts +1 -0
  52. package/dist/features/account/components/UserBidsView.js +47 -0
  53. package/dist/features/account/components/UserOrdersView.d.ts +4 -11
  54. package/dist/features/account/components/UserOrdersView.js +54 -4
  55. package/dist/features/account/components/UserReturnsView.d.ts +4 -9
  56. package/dist/features/account/components/UserReturnsView.js +37 -3
  57. package/dist/features/account/components/index.d.ts +3 -2
  58. package/dist/features/account/components/index.js +1 -0
  59. package/dist/features/admin/actions/admin-actions.js +22 -0
  60. package/dist/features/admin/actions/admin-coupon-actions.js +10 -0
  61. package/dist/features/admin/actions/notification-actions.js +4 -3
  62. package/dist/features/admin/components/AdminAdsView.d.ts +2 -3
  63. package/dist/features/admin/components/AdminAdsView.js +86 -89
  64. package/dist/features/admin/components/AdminAllEventEntriesView.js +18 -3
  65. package/dist/features/admin/components/AdminAuditLogView.d.ts +11 -0
  66. package/dist/features/admin/components/AdminAuditLogView.js +95 -0
  67. package/dist/features/admin/components/AdminBlogEditorView.js +37 -3
  68. package/dist/features/admin/components/AdminBrandEditorView.js +10 -6
  69. package/dist/features/admin/components/AdminBundleEditorView.js +18 -2
  70. package/dist/features/admin/components/AdminCarouselEditorView.js +2 -2
  71. package/dist/features/admin/components/AdminCarouselGroupEditorView.js +2 -2
  72. package/dist/features/admin/components/AdminCartsView.js +34 -4
  73. package/dist/features/admin/components/AdminCategoryEditorView.js +5 -4
  74. package/dist/features/admin/components/AdminCouponEditorView.js +2 -2
  75. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  76. package/dist/features/admin/components/AdminHistoryView.js +11 -1
  77. package/dist/features/admin/components/AdminNotificationsView.js +27 -1
  78. package/dist/features/admin/components/AdminOrderEditorView.d.ts +10 -1
  79. package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
  80. package/dist/features/admin/components/AdminOrdersView.js +92 -24
  81. package/dist/features/admin/components/AdminPayoutMarkPaidModal.d.ts +7 -0
  82. package/dist/features/admin/components/AdminPayoutMarkPaidModal.js +47 -0
  83. package/dist/features/admin/components/AdminPayoutsView.js +15 -31
  84. package/dist/features/admin/components/AdminProductEditorView.js +26 -3
  85. package/dist/features/admin/components/AdminSiteSettingsView.js +20 -1
  86. package/dist/features/admin/components/AdminStoreAddressesView.js +22 -2
  87. package/dist/features/admin/components/AdminStoresView.js +7 -0
  88. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +2 -2
  89. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +2 -2
  90. package/dist/features/admin/components/AdminUserEditorView.d.ts +2 -2
  91. package/dist/features/admin/components/AdminUserEditorView.js +4 -2
  92. package/dist/features/admin/components/AdminUsersView.js +1 -1
  93. package/dist/features/admin/components/AdminWishlistsView.js +14 -1
  94. package/dist/features/admin/components/DataListingView.d.ts +2 -2
  95. package/dist/features/admin/components/ViewAuditLogEntryModal.d.ts +19 -0
  96. package/dist/features/admin/components/ViewAuditLogEntryModal.js +22 -0
  97. package/dist/features/admin/components/ViewNotificationModal.d.ts +21 -0
  98. package/dist/features/admin/components/ViewNotificationModal.js +15 -0
  99. package/dist/features/admin/components/analytics/AdminPageViewsReportView.d.ts +4 -7
  100. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +56 -36
  101. package/dist/features/admin/components/index.d.ts +8 -1
  102. package/dist/features/admin/components/index.js +4 -0
  103. package/dist/features/admin/constants/filter-tabs.d.ts +49 -0
  104. package/dist/features/admin/constants/filter-tabs.js +27 -0
  105. package/dist/features/admin/hooks/useAdminListing.d.ts +6 -0
  106. package/dist/features/admin/hooks/useAdminListing.js +3 -1
  107. package/dist/features/admin/hooks/useAdminListingData.d.ts +9 -1
  108. package/dist/features/admin/hooks/useAdminListingData.js +9 -2
  109. package/dist/features/admin/repository/site-settings.repository.d.ts +5 -0
  110. package/dist/features/admin/schemas/firestore.d.ts +12 -0
  111. package/dist/features/analytics/types.d.ts +1 -1
  112. package/dist/features/analytics/types.js +8 -0
  113. package/dist/features/auctions/schemas/index.d.ts +5 -0
  114. package/dist/features/audit-log/repository/audit-log.repository.d.ts +45 -0
  115. package/dist/features/audit-log/repository/audit-log.repository.js +30 -0
  116. package/dist/features/audit-log/schemas/firestore.d.ts +59 -0
  117. package/dist/features/audit-log/schemas/firestore.js +35 -0
  118. package/dist/features/auth/actions/index.d.ts +0 -1
  119. package/dist/features/auth/actions/index.js +0 -1
  120. package/dist/features/auth/hooks/useAuth.d.ts +8 -35
  121. package/dist/features/auth/hooks/useAuth.js +21 -37
  122. package/dist/features/auth/permissions/constants.d.ts +1 -1
  123. package/dist/features/auth/permissions/constants.js +2 -0
  124. package/dist/features/blog/schemas/index.d.ts +32 -0
  125. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +31 -3
  126. package/dist/features/catalogue/components/CatalogueItemEditorView.js +2 -1
  127. package/dist/features/categories/components/BrandDetailPageView.js +14 -12
  128. package/dist/features/categories/components/CategoryDetailPageView.js +7 -3
  129. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.d.ts +14 -0
  130. package/dist/features/categories/components/CategoryHighlightsAndFaqSection.js +22 -0
  131. package/dist/features/categories/components/CategoryProductsView.d.ts +1 -5
  132. package/dist/features/categories/components/CategoryProductsView.js +1 -1
  133. package/dist/features/categories/components/CategorySelectorCreate.js +16 -2
  134. package/dist/features/categories/schemas/firestore.d.ts +19 -2
  135. package/dist/features/categories/schemas/index.d.ts +24 -3
  136. package/dist/features/categories/schemas/index.js +3 -1
  137. package/dist/features/categories/types/index.d.ts +7 -0
  138. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +17 -3
  139. package/dist/features/checkout/actions/checkout-value-otp-actions.js +101 -22
  140. package/dist/features/contact/components/ContactForm.js +17 -4
  141. package/dist/features/contact/email.d.ts +1 -0
  142. package/dist/features/contact/email.js +3 -0
  143. package/dist/features/events/components/AdminEventEditorView.js +54 -2
  144. package/dist/features/events/components/AdminEventEntriesView.d.ts +2 -16
  145. package/dist/features/events/components/AdminEventEntriesView.js +56 -89
  146. package/dist/features/events/components/EventFormDrawer.js +5 -1
  147. package/dist/features/events/components/EventRaffleEntryForm.d.ts +1 -3
  148. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  149. package/dist/features/events/schemas/index.d.ts +22 -0
  150. package/dist/features/grouped/repository/grouped-listings.repository.d.ts +4 -0
  151. package/dist/features/grouped/repository/grouped-listings.repository.js +18 -0
  152. package/dist/features/homepage/components/CharacterHotspotForm.js +202 -187
  153. package/dist/features/homepage/components/SectionCarousel.d.ts +1 -7
  154. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  155. package/dist/features/layout/TitleBarLayout.d.ts +1 -1
  156. package/dist/features/layout/TitleBarLayout.js +3 -3
  157. package/dist/features/media/MediaImage.js +39 -3
  158. package/dist/features/media/types/index.d.ts +10 -0
  159. package/dist/features/media/types/index.js +1 -0
  160. package/dist/features/media/upload/MediaUploadField.d.ts +7 -1
  161. package/dist/features/media/upload/MediaUploadField.js +11 -7
  162. package/dist/features/media/upload/video-poster.d.ts +2 -0
  163. package/dist/features/media/upload/video-poster.js +16 -1
  164. package/dist/features/media/upload/video-poster.test.js +1 -1
  165. package/dist/features/orders/components/OrderStatusTimeline.d.ts +12 -0
  166. package/dist/features/orders/components/OrderStatusTimeline.js +55 -0
  167. package/dist/features/orders/components/index.d.ts +2 -0
  168. package/dist/features/orders/components/index.js +1 -0
  169. package/dist/features/orders/constants/payment-window.d.ts +25 -0
  170. package/dist/features/orders/constants/payment-window.js +25 -0
  171. package/dist/features/orders/repository/orders.repository.d.ts +32 -0
  172. package/dist/features/orders/repository/orders.repository.js +56 -0
  173. package/dist/features/orders/schemas/index.d.ts +24 -24
  174. package/dist/features/orders/types/index.d.ts +33 -0
  175. package/dist/features/pre-orders/schemas/index.d.ts +5 -0
  176. package/dist/features/products/components/BidHistory.js +9 -1
  177. package/dist/features/products/components/GroupSettingsPanel.js +25 -3
  178. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  179. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +1 -4
  180. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  181. package/dist/features/products/components/ProductDetailActions.d.ts +1 -2
  182. package/dist/features/products/components/ProductDetailActions.js +1 -1
  183. package/dist/features/products/components/ProductGrid.js +15 -1
  184. package/dist/features/products/constants/action-defs.d.ts +1 -0
  185. package/dist/features/products/constants/action-defs.js +1 -0
  186. package/dist/features/products/schemas/index.d.ts +5 -0
  187. package/dist/features/promotions/components/CouponsIndexListing.d.ts +1 -3
  188. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  189. package/dist/features/search/components/SearchView.d.ts +1 -3
  190. package/dist/features/search/components/SearchView.js +1 -1
  191. package/dist/features/seller/components/QuickProductForm.js +2 -1
  192. package/dist/features/seller/components/SellerBidsView.js +66 -107
  193. package/dist/features/seller/components/SellerGoogleReviewsView.js +17 -1
  194. package/dist/features/seller/components/SellerOrdersView.d.ts +15 -3
  195. package/dist/features/seller/components/SellerOrdersView.js +134 -163
  196. package/dist/features/seller/components/SellerPayoutMethodsView.js +60 -48
  197. package/dist/features/seller/components/SellerPayoutSettingsView.js +69 -4
  198. package/dist/features/seller/components/SellerPayoutsView.d.ts +12 -0
  199. package/dist/features/seller/components/SellerPayoutsView.js +25 -5
  200. package/dist/features/seller/components/SellerProductShell.d.ts +10 -3
  201. package/dist/features/seller/components/SellerProductShell.js +89 -36
  202. package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +2 -7
  203. package/dist/features/seller/components/SellerProductsFilterDrawer.js +4 -4
  204. package/dist/features/seller/components/SellerProductsView.d.ts +2 -4
  205. package/dist/features/seller/components/SellerProductsView.js +131 -189
  206. package/dist/features/seller/components/SellerReviewsView.js +95 -133
  207. package/dist/features/seller/components/SellerShippingConfigsView.js +47 -67
  208. package/dist/features/seller/components/SellerShippingView.js +41 -4
  209. package/dist/features/seller/components/SellerStoreCategoriesView.js +51 -59
  210. package/dist/features/seller/components/SellerStorefrontView.d.ts +6 -1
  211. package/dist/features/seller/components/SellerStorefrontView.js +42 -5
  212. package/dist/features/seller/components/index.d.ts +2 -2
  213. package/dist/features/seller/components/index.js +2 -2
  214. package/dist/features/shell/FormShell.d.ts +24 -4
  215. package/dist/features/shell/FormShell.js +12 -6
  216. package/dist/features/shell/QuickFormDrawer.js +67 -12
  217. package/dist/features/shell/StepForm.d.ts +30 -1
  218. package/dist/features/shell/StepForm.js +47 -4
  219. package/dist/features/shell/index.d.ts +1 -1
  220. package/dist/features/shell/index.js +1 -1
  221. package/dist/features/shipments/components/AdminShipmentEditorView.js +2 -2
  222. package/dist/features/shipments/schemas/validation.d.ts +14 -4
  223. package/dist/features/tester/components/AdminTesterFeedbackListView.js +23 -2
  224. package/dist/features/tester/components/TesterChecklistStepRow.js +1 -1
  225. package/dist/features/tester/components/TesterHubView.js +3 -2
  226. package/dist/features/tester/seed-data/orders-tester-seed-data.js +9 -1
  227. package/dist/features/tester/seed-data/products-tester-seed-data.js +43 -32
  228. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +404 -15
  229. package/dist/index.d.ts +15 -3
  230. package/dist/index.js +22 -5
  231. package/dist/next/routing/route-map.d.ts +11 -0
  232. package/dist/next/routing/route-map.js +5 -0
  233. package/dist/providers/email-resend/provider.js +1 -0
  234. package/dist/providers/firebase-client/auth.d.ts +1 -0
  235. package/dist/providers/firebase-client/auth.js +7 -1
  236. package/dist/repositories/index.d.ts +1 -0
  237. package/dist/repositories/index.js +1 -0
  238. package/dist/schemas/registry.d.ts +61 -25
  239. package/dist/security/pii-mask.js +1 -1
  240. package/dist/seed/categories-seed-data.js +69 -0
  241. package/dist/seed/products-auctions-seed-data.js +11 -0
  242. package/dist/seed/products-standard-seed-data.js +93 -4
  243. package/dist/seed/site-settings-seed-data.js +13 -1
  244. package/dist/seed/store-extensions-seed-data.js +1 -1
  245. package/dist/server-entry.d.ts +2 -1
  246. package/dist/server-entry.js +20 -2
  247. package/dist/server.d.ts +7 -2
  248. package/dist/server.js +8 -3
  249. package/dist/styles.css +1 -1
  250. package/dist/tailwind-utilities.css +1 -1
  251. package/dist/ui/components/Form.d.ts +11 -2
  252. package/dist/ui/components/Form.js +4 -3
  253. package/dist/ui/components/FormField.d.ts +3 -1
  254. package/dist/ui/components/FormField.js +22 -4
  255. package/dist/ui/components/ListingLayout.d.ts +1 -2
  256. package/dist/ui/components/ListingLayout.js +1 -1
  257. package/dist/ui/components/RecordDetailModal.d.ts +68 -0
  258. package/dist/ui/components/RecordDetailModal.js +8 -0
  259. package/dist/ui/components/SlottedListingView.js +9 -1
  260. package/dist/ui/forms/FormErrorSummary.d.ts +25 -0
  261. package/dist/ui/forms/FormErrorSummary.js +37 -0
  262. package/dist/ui/forms/FormShell.d.ts +37 -2
  263. package/dist/ui/forms/FormShell.js +37 -7
  264. package/dist/ui/forms/FormShell.style.css +17 -0
  265. package/dist/ui/forms/index.d.ts +2 -0
  266. package/dist/ui/forms/index.js +1 -0
  267. package/dist/ui/index.d.ts +4 -0
  268. package/dist/ui/index.js +5 -0
  269. package/dist/utils/media-url.d.ts +3 -1
  270. package/dist/utils/media-url.js +20 -1
  271. package/dist/validation/schemas.d.ts +4 -4
  272. package/package.json +1 -1
  273. package/dist/_internal/client/features/classified/ClassifiedDetailView.d.ts +0 -9
  274. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +0 -55
  275. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.d.ts +0 -18
  276. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +0 -21
  277. package/dist/_internal/client/features/live/LiveItemDetailView.d.ts +0 -9
  278. package/dist/_internal/client/features/live/LiveItemDetailView.js +0 -25
  279. package/dist/_internal/server/jobs/core/prizeRevealClose.d.ts +0 -2
  280. package/dist/_internal/server/jobs/core/prizeRevealClose.js +0 -28
  281. package/dist/_internal/server/jobs/core/prizeRevealExpiry.d.ts +0 -2
  282. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +0 -61
  283. package/dist/_internal/server/jobs/core/prizeRevealOpen.d.ts +0 -2
  284. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +0 -68
  285. package/dist/_internal/server/jobs/core/prizeRevealReminder.d.ts +0 -2
  286. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +0 -49
  287. package/dist/_internal/server/jobs/handlers/prizeRevealClose.d.ts +0 -2
  288. package/dist/_internal/server/jobs/handlers/prizeRevealClose.js +0 -2
  289. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.d.ts +0 -2
  290. package/dist/_internal/server/jobs/handlers/prizeRevealExpiry.js +0 -2
  291. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.d.ts +0 -2
  292. package/dist/_internal/server/jobs/handlers/prizeRevealOpen.js +0 -2
  293. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.d.ts +0 -2
  294. package/dist/_internal/server/jobs/handlers/prizeRevealReminder.js +0 -2
  295. package/dist/features/auth/consent-otp.d.ts +0 -57
  296. package/dist/features/auth/consent-otp.js +0 -127
  297. package/dist/features/cart/components/CheckoutOtpModal.d.ts +0 -15
  298. package/dist/features/cart/components/CheckoutOtpModal.js +0 -12
  299. package/dist/features/checkout/actions/checkout-actions.d.ts +0 -31
  300. package/dist/features/checkout/actions/checkout-actions.js +0 -124
  301. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +0 -5
  302. package/dist/features/classified/components/ClassifiedIndexListing.js +0 -123
  303. package/dist/features/classified/components/ClassifiedListView.d.ts +0 -6
  304. package/dist/features/classified/components/ClassifiedListView.js +0 -44
  305. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +0 -5
  306. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +0 -114
  307. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +0 -6
  308. package/dist/features/digital-codes/components/DigitalCodesListView.js +0 -38
  309. package/dist/features/live/components/LiveItemsIndexListing.d.ts +0 -5
  310. package/dist/features/live/components/LiveItemsIndexListing.js +0 -115
  311. package/dist/features/live/components/LiveItemsListView.d.ts +0 -6
  312. package/dist/features/live/components/LiveItemsListView.js +0 -44
  313. package/dist/features/seller/components/SellerTemplatesView.d.ts +0 -12
  314. package/dist/features/seller/components/SellerTemplatesView.js +0 -276
  315. package/dist/react/hooks/useVisibleItems.d.ts +0 -37
  316. package/dist/react/hooks/useVisibleItems.js +0 -59
  317. package/dist/ui/components/TabStrip.d.ts +0 -34
  318. package/dist/ui/components/TabStrip.js +0 -56
  319. package/dist/ui/components/TabStrip.style.css +0 -97
@@ -1,9 +0,0 @@
1
- import React from "react";
2
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
3
- import type { startClassifiedConversationAction } from "../../../server/features/classified/actions";
4
- export interface ClassifiedDetailViewProps {
5
- product: ProductDocument | null;
6
- isLoading?: boolean;
7
- onContactSeller: typeof startClassifiedConversationAction;
8
- }
9
- export declare function ClassifiedDetailView({ product, isLoading, onContactSeller, }: ClassifiedDetailViewProps): React.JSX.Element;
@@ -1,55 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { normalizeError } from "../../../../errors/normalize";
4
- import { useState } from "react";
5
- import Link from "next/link";
6
- import { Badge, Button, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
7
- import { MediaImage } from "../../../../features/media/MediaImage";
8
- import { ROUTES } from "../../../../next/routing/route-map";
9
- import { formatCurrency } from "../../../../utils/number.formatter";
10
- const __P = {
11
- p4: "p-[var(--appkit-space-4)]",
12
- };
13
- const __O = {
14
- hidden: "overflow-hidden",
15
- };
16
- export function ClassifiedDetailView({ product, isLoading = false, onContactSeller, }) {
17
- const [pending, setPending] = useState(false);
18
- const [conversation, setConversation] = useState(null);
19
- const [error, setError] = useState(null);
20
- if (isLoading || !product) {
21
- return (_jsx(Container, { children: _jsx(Div, { className: "text-center", padding: "y-4xl", children: _jsx(Text, { className: "text-muted-foreground", children: isLoading ? "Loading…" : "Classified listing not found." }) }) }));
22
- }
23
- const meta = product.classified;
24
- const price = formatCurrency(product.price, product.currency ?? "INR");
25
- const location = meta?.meetupArea
26
- ? [meta.meetupArea.locality, meta.meetupArea.city].filter(Boolean).join(", ")
27
- : null;
28
- async function handleContactSeller() {
29
- setPending(true);
30
- setError(null);
31
- try {
32
- const result = await onContactSeller({ productId: product.id });
33
- // ActionResult envelope — unwrap or surface
34
- if (result && typeof result === "object" && "ok" in result) {
35
- if (result.ok) {
36
- setConversation(result.data);
37
- }
38
- else {
39
- setError(result.error);
40
- }
41
- }
42
- else {
43
- setConversation(result);
44
- }
45
- }
46
- catch (e) {
47
- void normalizeError(e);
48
- setError(e instanceof Error ? e.message : "Something went wrong");
49
- }
50
- finally {
51
- setPending(false);
52
- }
53
- }
54
- return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Classified" }), meta?.negotiable && _jsx(Badge, { variant: "secondary", children: "Negotiable" }), meta?.acceptsShipping && _jsx(Badge, { variant: "secondary", children: "Shipping available" })] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), location && (_jsx(Text, { className: "text-muted-foreground", size: "sm", children: location })), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), conversation ? (_jsxs(Div, { className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { className: "mb-2", weight: "medium", children: "Conversation started!" }), _jsx(Link, { href: ROUTES.USER.MESSAGES, className: "text-primary underline underline-offset-2", children: "Go to your messages \u2192" })] })) : (_jsxs(Stack, { gap: "sm", children: [error && (_jsx(Text, { className: "text-destructive", size: "sm", children: error })), _jsx(Button, { type: "button", variant: "primary", size: "lg", isLoading: pending, disabled: pending, onClick: handleContactSeller, className: "w-full", children: "Contact Seller" })] }))] }) }) }));
55
- }
@@ -1,18 +0,0 @@
1
- import React from "react";
2
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
3
- import type { RevealedCode } from "./CodeRevealPanel";
4
- export interface DigitalCodeDetailViewProps {
5
- product: ProductDocument | null;
6
- isLoading?: boolean;
7
- /**
8
- * Set when the buyer has a confirmed order for this product and wants to
9
- * reveal their code. The page shim wires this from the order context.
10
- */
11
- orderId?: string;
12
- /**
13
- * Injected from the page so the panel never hard-codes the API path.
14
- * Required when orderId is set.
15
- */
16
- fetchCode?: (orderId: string) => Promise<RevealedCode>;
17
- }
18
- export declare function DigitalCodeDetailView({ product, isLoading, orderId, fetchCode, }: DigitalCodeDetailViewProps): React.JSX.Element;
@@ -1,21 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Badge, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
4
- import { MediaImage } from "../../../../features/media/MediaImage";
5
- import { formatCurrency } from "../../../../utils/number.formatter";
6
- import { CodeRevealPanel } from "./CodeRevealPanel";
7
- const __P = {
8
- p4: "p-[var(--appkit-space-4)]",
9
- };
10
- const __O = {
11
- hidden: "overflow-hidden",
12
- };
13
- export function DigitalCodeDetailView({ product, isLoading = false, orderId, fetchCode, }) {
14
- if (isLoading || !product) {
15
- return (_jsx(Container, { children: _jsx(Div, { className: "text-center", padding: "y-4xl", children: _jsx(Text, { className: "text-muted-foreground", children: isLoading ? "Loading…" : "Digital code listing not found." }) }) }));
16
- }
17
- const meta = product.digitalCode;
18
- const price = formatCurrency(product.price, product.currency ?? "INR");
19
- const codesLeft = meta?.codesAvailable ?? 0;
20
- return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Digital Code" }), codesLeft > 0 ? (_jsxs(Badge, { variant: "active", children: [codesLeft, " available"] })) : (_jsx(Badge, { variant: "danger", children: "Sold out" }))] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), orderId && fetchCode ? (_jsx(CodeRevealPanel, { orderId: orderId, redemptionInstructions: meta?.redemptionInstructions, fetchCode: fetchCode })) : (_jsxs(Div, { className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { className: "text-muted-foreground", size: "sm", children: "After purchase, return to your order to reveal the code instantly." }), meta?.redemptionInstructions && (_jsx(Text, { className: "mt-2", size: "sm", children: meta.redemptionInstructions }))] }))] }) }) }));
21
- }
@@ -1,9 +0,0 @@
1
- import React from "react";
2
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
3
- export interface LiveItemDetailViewProps {
4
- product: ProductDocument | null;
5
- isLoading?: boolean;
6
- /** Render-prop for the add-to-cart CTA — wired by the page shim. */
7
- renderActions?: () => React.ReactNode;
8
- }
9
- export declare function LiveItemDetailView({ product, isLoading, renderActions, }: LiveItemDetailViewProps): React.JSX.Element;
@@ -1,25 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Badge, Container, Div, Heading, Row, Section, Stack, Text, } from "../../../../ui";
4
- import { MediaImage } from "../../../../features/media/MediaImage";
5
- import { formatCurrency } from "../../../../utils/number.formatter";
6
- const __P = {
7
- p4: "p-[var(--appkit-space-4)]",
8
- };
9
- const __O = {
10
- hidden: "overflow-hidden",
11
- };
12
- const CLS_WARN_BOX = "rounded-lg border border-warning bg-warning-surface p-[var(--appkit-space-4)] text-[length:var(--appkit-text-sm)]";
13
- const CLS_WARN_TITLE = "font-medium text-warning";
14
- const CLS_WARN_BODY = "mt-1 text-warning";
15
- export function LiveItemDetailView({ product, isLoading = false, renderActions, }) {
16
- if (isLoading || !product) {
17
- return (_jsx(Container, { children: _jsx(Div, { className: "text-center", padding: "y-4xl", children: _jsx(Text, { className: "text-muted-foreground", children: isLoading ? "Loading…" : "Live listing not found." }) }) }));
18
- }
19
- const meta = product.liveItem;
20
- const price = formatCurrency(product.price, product.currency ?? "INR");
21
- const jurisdictions = meta?.jurisdictionAllowed ?? [];
22
- const transport = meta?.transport;
23
- return (_jsx(Container, { children: _jsx(Section, { padding: "y-xl", children: _jsxs(Stack, { gap: "lg", children: [product.images.length > 0 && (_jsx(Div, { className: `relative h-80 w-full ${__O.hidden} bg-muted`, rounded: "lg", children: _jsx(MediaImage, { src: product.mainImage || product.images[0], alt: product.title, size: "hero", objectFit: "contain" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", wrap: true, children: [_jsx(Badge, { variant: "secondary", children: "Live Item" }), meta?.vendorVerified && (_jsx(Badge, { variant: "active", children: "Verified Seller" })), meta?.cites && (_jsxs(Badge, { variant: "warning", children: ["CITES: ", meta.cites] }))] }), _jsx(Heading, { level: 1, weight: "bold", size: "2xl", children: product.title }), meta?.species && (_jsxs(Text, { className: "italic text-muted-foreground", size: "sm", children: [meta.species, meta.sex && meta.sex !== "n/a" && ` · ${meta.sex}`, meta.ageMonths !== undefined && ` · ${meta.ageMonths}mo`] })), _jsx(Text, { className: "text-primary", size: "2xl", weight: "semibold", children: price }), _jsx(Text, { className: "text-muted-foreground", children: product.description })] }), jurisdictions.length > 0 && (_jsxs(Div, { className: CLS_WARN_BOX, children: [_jsx(Text, { className: CLS_WARN_TITLE, children: "Delivery restrictions" }), _jsxs(Text, { className: CLS_WARN_BODY, children: ["This item can only be shipped to: ", jurisdictions.join(", ")] })] })), transport && (_jsxs(Div, { textSize: "sm", className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Transport" }), _jsxs(Text, { className: "text-muted-foreground", children: ["Method: ", transport.method, transport.handlingFee !== undefined &&
24
- ` · Handling: ${formatCurrency(transport.handlingFee, "INR")}`, transport.insuranceIncluded && " · Insurance included"] })] })), meta?.careInfo && (_jsxs(Div, { textSize: "sm", className: `border border-border bg-muted/40 ${__P.p4}`, rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Care information" }), _jsx(Text, { className: "mt-1 text-muted-foreground", children: meta.careInfo })] })), renderActions?.()] }) }) }));
25
- }
@@ -1,2 +0,0 @@
1
- import type { JobContext } from "../runtime/types";
2
- export declare function runPrizeRevealClose(ctx: JobContext): Promise<void>;
@@ -1,28 +0,0 @@
1
- import { PRODUCT_FIELDS, COMMON_FIELDS } from "../../../../constants/field-names";
2
- const PRODUCT_COLLECTION = "products";
3
- const PRIZE_DRAW_LISTING_TYPE = "prize-draw";
4
- export async function runPrizeRevealClose(ctx) {
5
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
6
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize reveal close");
7
- return;
8
- }
9
- ctx.logger.info("Prize reveal close sweep starting");
10
- const snap = await ctx.db
11
- .collection(PRODUCT_COLLECTION)
12
- .where(PRODUCT_FIELDS.LISTING_TYPE, "==", PRIZE_DRAW_LISTING_TYPE)
13
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_STATUS, "==", PRODUCT_FIELDS.PRIZE_REVEAL_STATUS_VALUES.OPEN)
14
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_WINDOW_END, "<=", ctx.now)
15
- .limit(100)
16
- .get();
17
- if (snap.empty) {
18
- ctx.logger.info("No prize draws to close");
19
- return;
20
- }
21
- const batch = ctx.db.batch();
22
- snap.docs.forEach((doc) => batch.update(doc.ref, {
23
- [PRODUCT_FIELDS.PRIZE_REVEAL_STATUS]: PRODUCT_FIELDS.PRIZE_REVEAL_STATUS_VALUES.CLOSED,
24
- [COMMON_FIELDS.UPDATED_AT]: ctx.now,
25
- }));
26
- await batch.commit();
27
- ctx.logger.info("Closed prize draws", { count: snap.size });
28
- }
@@ -1,2 +0,0 @@
1
- import type { JobContext } from "../runtime/types";
2
- export declare function runPrizeRevealExpiry(ctx: JobContext): Promise<void>;
@@ -1,61 +0,0 @@
1
- import { normalizeError } from "../../../../errors/normalize";
2
- import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
- import { ORDER_FIELDS, PRODUCT_FIELDS, COMMON_FIELDS } from "../../../../constants/field-names";
4
- const ORDER_COLLECTION = "orders";
5
- export async function runPrizeRevealExpiry(ctx) {
6
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
7
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize reveal expiry");
8
- return;
9
- }
10
- ctx.logger.info("Prize reveal expiry sweep starting");
11
- const snap = await ctx.db
12
- .collection(ORDER_COLLECTION)
13
- .where(ORDER_FIELDS.PAYMENT_STATUS, "==", ORDER_FIELDS.PAYMENT_STATUS_VALUES.PAID)
14
- .where(ORDER_FIELDS.STATUS, "in", [
15
- ORDER_FIELDS.STATUS_VALUES.PENDING,
16
- ORDER_FIELDS.STATUS_VALUES.CONFIRMED,
17
- ORDER_FIELDS.STATUS_VALUES.PROCESSING,
18
- ])
19
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_DEADLINE, "<", ctx.now)
20
- .limit(200)
21
- .get();
22
- if (snap.empty) {
23
- ctx.logger.info("No prize-draw orders past deadline");
24
- return;
25
- }
26
- let refunded = 0;
27
- for (const doc of snap.docs) {
28
- const order = doc.data();
29
- if (order.prizeWon)
30
- continue;
31
- if (!order.prizeDrawProductId)
32
- continue;
33
- await doc.ref.update({
34
- [ORDER_FIELDS.STATUS]: ORDER_FIELDS.STATUS_VALUES.REFUNDED,
35
- [ORDER_FIELDS.PAYMENT_STATUS]: ORDER_FIELDS.PAYMENT_STATUS_VALUES.REFUNDED,
36
- isNonRefundable: false,
37
- prizeRevealExpired: true,
38
- [COMMON_FIELDS.UPDATED_AT]: ctx.now,
39
- });
40
- if (order.userId) {
41
- try {
42
- await sendNotification({
43
- userId: order.userId,
44
- type: "prize_reveal_expired",
45
- priority: "high",
46
- title: "Reveal deadline passed — refunded",
47
- message: `Your entry for "${order.productTitle ?? "the draw"}" expired without a reveal. We've refunded the order.`,
48
- relatedId: doc.id,
49
- relatedType: "order",
50
- actionUrl: `/user/orders/view/${doc.id}`,
51
- });
52
- }
53
- catch (err) {
54
- void normalizeError(err);
55
- ctx.logger.warn("Reveal-expired notification failed", { err: err instanceof Error ? err.message : String(err) });
56
- }
57
- }
58
- refunded++;
59
- }
60
- ctx.logger.info("Prize reveal expiry sweep complete", { refunded });
61
- }
@@ -1,2 +0,0 @@
1
- import type { JobContext } from "../runtime/types";
2
- export declare function runPrizeRevealOpen(ctx: JobContext): Promise<void>;
@@ -1,68 +0,0 @@
1
- import { normalizeError } from "../../../../errors/normalize";
2
- import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
- import { PRODUCT_FIELDS, ORDER_FIELDS, COMMON_FIELDS } from "../../../../constants/field-names";
4
- const PRODUCT_COLLECTION = "products";
5
- const ORDER_COLLECTION = "orders";
6
- const PRIZE_DRAW_LISTING_TYPE = "prize-draw";
7
- export async function runPrizeRevealOpen(ctx) {
8
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
9
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize reveal open");
10
- return;
11
- }
12
- ctx.logger.info("Prize reveal open sweep starting");
13
- const snap = await ctx.db
14
- .collection(PRODUCT_COLLECTION)
15
- .where(PRODUCT_FIELDS.LISTING_TYPE, "==", PRIZE_DRAW_LISTING_TYPE)
16
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_STATUS, "==", PRODUCT_FIELDS.PRIZE_REVEAL_STATUS_VALUES.PENDING)
17
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_WINDOW_START, "<=", ctx.now)
18
- .limit(100)
19
- .get();
20
- if (snap.empty) {
21
- ctx.logger.info("No prize draws to open");
22
- return;
23
- }
24
- for (const doc of snap.docs) {
25
- const product = doc.data();
26
- await doc.ref.update({
27
- [PRODUCT_FIELDS.PRIZE_REVEAL_STATUS]: PRODUCT_FIELDS.PRIZE_REVEAL_STATUS_VALUES.OPEN,
28
- [COMMON_FIELDS.UPDATED_AT]: ctx.now,
29
- });
30
- const orders = await ctx.db
31
- .collection(ORDER_COLLECTION)
32
- .where("prizeDrawProductId", "==", doc.id)
33
- .where(ORDER_FIELDS.PAYMENT_STATUS, "==", ORDER_FIELDS.PAYMENT_STATUS_VALUES.PAID)
34
- .where(ORDER_FIELDS.STATUS, "in", [
35
- ORDER_FIELDS.STATUS_VALUES.PENDING,
36
- ORDER_FIELDS.STATUS_VALUES.CONFIRMED,
37
- ORDER_FIELDS.STATUS_VALUES.PROCESSING,
38
- ])
39
- .get();
40
- let notified = 0;
41
- for (const orderDoc of orders.docs) {
42
- const order = orderDoc.data();
43
- if (!order.userId || order.prizeWon)
44
- continue;
45
- try {
46
- await sendNotification({
47
- userId: order.userId,
48
- type: "prize_reveal_ready",
49
- priority: "high",
50
- title: "Your reveal is ready!",
51
- message: `Reveal your prize for "${product.title ?? "draw"}". You have ${product.prizeRevealDeadlineDays ?? 3} days to claim it.`,
52
- relatedId: orderDoc.id,
53
- relatedType: "order",
54
- actionUrl: `/user/orders/view/${orderDoc.id}`,
55
- });
56
- notified++;
57
- }
58
- catch (err) {
59
- void normalizeError(err);
60
- ctx.logger.warn("Reveal-ready notification failed", { err: err instanceof Error ? err.message : String(err) });
61
- }
62
- }
63
- ctx.logger.info("Opened prize draw", {
64
- productId: doc.id,
65
- buyersNotified: notified,
66
- });
67
- }
68
- }
@@ -1,2 +0,0 @@
1
- import type { JobContext } from "../runtime/types";
2
- export declare function runPrizeRevealReminder(ctx: JobContext): Promise<void>;
@@ -1,49 +0,0 @@
1
- import { normalizeError } from "../../../../errors/normalize";
2
- import { sendNotification } from "../../../../features/admin/actions/notification-actions";
3
- import { ORDER_FIELDS, PRODUCT_FIELDS } from "../../../../constants/field-names";
4
- const ORDER_COLLECTION = "orders";
5
- const ONE_DAY_MS = 86400000;
6
- export async function runPrizeRevealReminder(ctx) {
7
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
8
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize reveal reminder");
9
- return;
10
- }
11
- ctx.logger.info("Prize reveal reminder sweep starting");
12
- const cutoff = new Date(ctx.now.getTime() + ONE_DAY_MS);
13
- const snap = await ctx.db
14
- .collection(ORDER_COLLECTION)
15
- .where(ORDER_FIELDS.PAYMENT_STATUS, "==", ORDER_FIELDS.PAYMENT_STATUS_VALUES.PAID)
16
- .where(ORDER_FIELDS.STATUS, "in", [
17
- ORDER_FIELDS.STATUS_VALUES.PENDING,
18
- ORDER_FIELDS.STATUS_VALUES.CONFIRMED,
19
- ORDER_FIELDS.STATUS_VALUES.PROCESSING,
20
- ])
21
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_DEADLINE, "<=", cutoff)
22
- .where(PRODUCT_FIELDS.PRIZE_REVEAL_DEADLINE, ">", ctx.now)
23
- .limit(500)
24
- .get();
25
- let notified = 0;
26
- for (const doc of snap.docs) {
27
- const order = doc.data();
28
- if (!order.userId || order.prizeWon || !order.prizeDrawProductId)
29
- continue;
30
- try {
31
- await sendNotification({
32
- userId: order.userId,
33
- type: "prize_reveal_reminder",
34
- priority: "normal",
35
- title: "Reveal expires within 24h",
36
- message: `Reveal your prize for "${order.productTitle ?? "the draw"}" today — unclaimed reveals are auto-refunded after the deadline.`,
37
- relatedId: doc.id,
38
- relatedType: "order",
39
- actionUrl: `/user/orders/view/${doc.id}`,
40
- });
41
- notified++;
42
- }
43
- catch (err) {
44
- void normalizeError(err);
45
- ctx.logger.warn("Reveal reminder notification failed", { err: err instanceof Error ? err.message : String(err) });
46
- }
47
- }
48
- ctx.logger.info("Prize reveal reminder sweep complete", { notified });
49
- }
@@ -1,2 +0,0 @@
1
- import type { ScheduleHandler } from "../runtime/types";
2
- export declare const prizeRevealCloseHandler: ScheduleHandler;
@@ -1,2 +0,0 @@
1
- import { runPrizeRevealClose } from "../core/prizeRevealClose";
2
- export const prizeRevealCloseHandler = runPrizeRevealClose;
@@ -1,2 +0,0 @@
1
- import type { ScheduleHandler } from "../runtime/types";
2
- export declare const prizeRevealExpiryHandler: ScheduleHandler;
@@ -1,2 +0,0 @@
1
- import { runPrizeRevealExpiry } from "../core/prizeRevealExpiry";
2
- export const prizeRevealExpiryHandler = runPrizeRevealExpiry;
@@ -1,2 +0,0 @@
1
- import type { ScheduleHandler } from "../runtime/types";
2
- export declare const prizeRevealOpenHandler: ScheduleHandler;
@@ -1,2 +0,0 @@
1
- import { runPrizeRevealOpen } from "../core/prizeRevealOpen";
2
- export const prizeRevealOpenHandler = runPrizeRevealOpen;
@@ -1,2 +0,0 @@
1
- import type { ScheduleHandler } from "../runtime/types";
2
- export declare const prizeRevealReminderHandler: ScheduleHandler;
@@ -1,2 +0,0 @@
1
- import { runPrizeRevealReminder } from "../core/prizeRevealReminder";
2
- export const prizeRevealReminderHandler = runPrizeRevealReminder;
@@ -1,57 +0,0 @@
1
- /**
2
- * Consent OTP - Shared constants, path helpers, and utilities
3
- */
4
- import type { FirestoreDocument } from "@mohasinac/appkit";
5
- import { getAdminDb } from "../../providers/db-firebase";
6
- /** OTP validity window (10 minutes). */
7
- export declare const CONSENT_OTP_EXPIRY_MS: number;
8
- /** Used in email body text so it stays in sync with CONSENT_OTP_EXPIRY_MS. */
9
- export declare const CONSENT_OTP_EXPIRY_MINUTES = 10;
10
- /** Per-user send cooldown (15 minutes). */
11
- export declare const CONSENT_OTP_COOLDOWN_MS: number;
12
- /** Maximum number of partial-order bypass credits a user can accumulate. */
13
- export declare const CONSENT_OTP_MAX_BYPASS_CREDITS = 3;
14
- /** Maximum failed verification attempts before the OTP is locked. */
15
- export declare const CONSENT_OTP_MAX_ATTEMPTS = 5;
16
- /** Rate-limit config for the verify endpoint / action (10 attempts per 5 min). */
17
- export declare const CONSENT_OTP_VERIFY_RATE_LIMIT: {
18
- readonly limit: 10;
19
- readonly window: 300;
20
- };
21
- type Db = ReturnType<typeof getAdminDb>;
22
- /** Reference to a user's consent OTP document for a given address. */
23
- export declare function consentOtpRef(db: Db, uid: string, addressId: string): FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
24
- /** Reference to a user's consent OTP rate-limit metadata document. */
25
- export declare function consentOtpRateLimitRef(db: Db, uid: string): FirebaseFirestore.DocumentReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
26
- /** HMAC-SHA256 hash of an OTP code. */
27
- export declare function hashOtp(code: string): string;
28
- /** Generate a cryptographically-secure random 6-digit OTP string. */
29
- export declare function generateOtpCode(): string;
30
- /** Obfuscate an email address for display (e.g. j***e@example.com). */
31
- export declare function maskEmail(email: string): string;
32
- /** Shape of a consent OTP document as returned from Firestore. */
33
- export interface ConsentOtpDoc {
34
- codeHash: string;
35
- expiresAt: FirebaseFirestore.Timestamp;
36
- attempts: number;
37
- verified: boolean;
38
- }
39
- /**
40
- * Enforce the per-user send rate-limit.
41
- * Throws AuthorizationError("consentOtpRateLimit") when throttled and no bypass credits remain.
42
- */
43
- export declare function enforceConsentOtpRateLimit(uid: string): Promise<void>;
44
- /** Write (or overwrite) a consent OTP document for a given user + address. */
45
- export declare function saveConsentOtp(uid: string, addressId: string, data: FirestoreDocument): Promise<void>;
46
- /** Read a consent OTP document. Returns null when the document does not exist. */
47
- export declare function readConsentOtp(uid: string, addressId: string): Promise<ConsentOtpDoc | null>;
48
- /** Partially update a consent OTP document. */
49
- export declare function patchConsentOtp(uid: string, addressId: string, data: FirestoreDocument): Promise<void>;
50
- /** Build the consent OTP WhatsApp message body. */
51
- export declare function buildConsentOtpWhatsApp(recipientName: string, code: string, siteName: string): string;
52
- /** Build the consent OTP email subject and HTML body. */
53
- export declare function buildConsentOtpEmail(recipientName: string, code: string, siteName: string): {
54
- subject: string;
55
- html: string;
56
- };
57
- export {};
@@ -1,127 +0,0 @@
1
- /**
2
- * Consent OTP - Shared constants, path helpers, and utilities
3
- */
4
- import { createHmac, randomInt } from "crypto";
5
- import { getAdminDb } from "../../providers/db-firebase";
6
- import { AuthorizationError } from "../../errors";
7
- import { escapeHtml, resolveDate } from "../../utils";
8
- import { USER_COLLECTION } from "./schemas";
9
- const HMAC_KEY = process.env.CONSENT_OTP_HMAC_KEY ||
10
- process.env.HMAC_SECRET ||
11
- "consent-otp-secret";
12
- /** OTP validity window (10 minutes). */
13
- export const CONSENT_OTP_EXPIRY_MS = 10 * 60 * 1000;
14
- /** Used in email body text so it stays in sync with CONSENT_OTP_EXPIRY_MS. */
15
- export const CONSENT_OTP_EXPIRY_MINUTES = 10;
16
- /** Per-user send cooldown (15 minutes). */
17
- export const CONSENT_OTP_COOLDOWN_MS = 15 * 60 * 1000;
18
- /** Maximum number of partial-order bypass credits a user can accumulate. */
19
- export const CONSENT_OTP_MAX_BYPASS_CREDITS = 3;
20
- /** Maximum failed verification attempts before the OTP is locked. */
21
- export const CONSENT_OTP_MAX_ATTEMPTS = 5;
22
- /** Rate-limit config for the verify endpoint / action (10 attempts per 5 min). */
23
- export const CONSENT_OTP_VERIFY_RATE_LIMIT = {
24
- limit: 10,
25
- window: 300,
26
- };
27
- /** Reference to a user's consent OTP document for a given address. */
28
- export function consentOtpRef(db, uid, addressId) {
29
- return db
30
- .collection(USER_COLLECTION)
31
- .doc(uid)
32
- .collection("consentOtps")
33
- .doc(addressId);
34
- }
35
- /** Reference to a user's consent OTP rate-limit metadata document. */
36
- export function consentOtpRateLimitRef(db, uid) {
37
- return db
38
- .collection(USER_COLLECTION)
39
- .doc(uid)
40
- .collection("consentOtpRateLimit")
41
- .doc("meta");
42
- }
43
- /** HMAC-SHA256 hash of an OTP code. */
44
- export function hashOtp(code) {
45
- return createHmac("sha256", HMAC_KEY).update(code).digest("hex");
46
- }
47
- /** Generate a cryptographically-secure random 6-digit OTP string. */
48
- export function generateOtpCode() {
49
- return String(randomInt(100000, 1000000));
50
- }
51
- /** Obfuscate an email address for display (e.g. j***e@example.com). */
52
- export function maskEmail(email) {
53
- const [local, domain] = email.split("@");
54
- if (!domain)
55
- return "***";
56
- const masked = local.length <= 2
57
- ? "*".repeat(local.length)
58
- : local[0] + "*".repeat(local.length - 2) + local[local.length - 1];
59
- return `${masked}@${domain}`;
60
- }
61
- /**
62
- * Enforce the per-user send rate-limit.
63
- * Throws AuthorizationError("consentOtpRateLimit") when throttled and no bypass credits remain.
64
- */
65
- export async function enforceConsentOtpRateLimit(uid) {
66
- const db = getAdminDb();
67
- const metaRef = consentOtpRateLimitRef(db, uid);
68
- await db.runTransaction(async (tx) => {
69
- const metaSnap = await tx.get(metaRef);
70
- const meta = metaSnap.exists
71
- ? metaSnap.data()
72
- : null;
73
- const lastSentMs = resolveDate(meta?.lastSentAt)?.getTime() ?? 0;
74
- const bypassCredits = meta?.bypassCredits ?? 0;
75
- const elapsed = Date.now() - lastSentMs;
76
- if (elapsed < CONSENT_OTP_COOLDOWN_MS) {
77
- if (bypassCredits <= 0) {
78
- throw new AuthorizationError("consentOtpRateLimit");
79
- }
80
- tx.set(metaRef, { lastSentAt: new Date(), bypassCredits: bypassCredits - 1 }, { merge: true });
81
- }
82
- else {
83
- tx.set(metaRef, { lastSentAt: new Date() }, { merge: true });
84
- }
85
- });
86
- }
87
- /** Write (or overwrite) a consent OTP document for a given user + address. */
88
- export async function saveConsentOtp(uid, addressId, data) {
89
- const db = getAdminDb();
90
- await consentOtpRef(db, uid, addressId).set(data);
91
- }
92
- /** Read a consent OTP document. Returns null when the document does not exist. */
93
- export async function readConsentOtp(uid, addressId) {
94
- const db = getAdminDb();
95
- const snap = await consentOtpRef(db, uid, addressId).get();
96
- if (!snap.exists)
97
- return null;
98
- return snap.data();
99
- }
100
- /** Partially update a consent OTP document. */
101
- export async function patchConsentOtp(uid, addressId, data) {
102
- const db = getAdminDb();
103
- await consentOtpRef(db, uid, addressId).update(data);
104
- }
105
- /** Build the consent OTP WhatsApp message body. */
106
- export function buildConsentOtpWhatsApp(recipientName, code, siteName) {
107
- return (`*${siteName} — Consent OTP*\n\n` +
108
- `You are shipping to *${recipientName}*.\n\n` +
109
- `Your verification code is: *${code}*\n\n` +
110
- `This code expires in ${CONSENT_OTP_EXPIRY_MINUTES} minutes. ` +
111
- `If you did not request this, please ignore this message.`);
112
- }
113
- /** Build the consent OTP email subject and HTML body. */
114
- export function buildConsentOtpEmail(recipientName, code, siteName) {
115
- return {
116
- subject: `${siteName}: Consent verification code - shipping to ${recipientName}`,
117
- html: `
118
- <div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
119
- <h2 style="margin-bottom:8px">Third-Party Shipping Consent</h2>
120
- <p style="color:#555">You are about to place an order that will be shipped to <strong>${escapeHtml(recipientName)}</strong>.</p>
121
- <p style="color:#555">Enter this code to confirm your consent:</p>
122
- <div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
123
- <p style="color:#888;font-size:12px">This code expires in ${CONSENT_OTP_EXPIRY_MINUTES} minutes. If you did not request this, please ignore this email.</p>
124
- </div>
125
- `,
126
- };
127
- }
@@ -1,15 +0,0 @@
1
- import React from "react";
2
- export interface CheckoutOtpModalProps {
3
- isOpen: boolean;
4
- title?: string;
5
- onClose: () => void;
6
- renderContainer: (context: {
7
- isOpen: boolean;
8
- title?: string;
9
- onClose: () => void;
10
- children: React.ReactNode;
11
- }) => React.ReactNode;
12
- renderBody: () => React.ReactNode;
13
- className?: string;
14
- }
15
- export declare function CheckoutOtpModal({ isOpen, title, onClose, renderContainer, renderBody, className, }: CheckoutOtpModalProps): React.JSX.Element | null;
@@ -1,12 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Div } from "../../../ui";
3
- export function CheckoutOtpModal({ isOpen, title, onClose, renderContainer, renderBody, className = "", }) {
4
- if (!isOpen)
5
- return null;
6
- return (_jsx(_Fragment, { children: renderContainer({
7
- isOpen,
8
- title,
9
- onClose,
10
- children: _jsx(Div, { className: className, children: renderBody() }),
11
- }) }));
12
- }