@mohasinac/appkit 3.0.4 → 3.1.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 (320) hide show
  1. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +42 -0
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +86 -0
  3. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +14 -0
  4. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +46 -0
  5. package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +28 -0
  6. package/dist/_internal/client/features/lottery/LotteryDetailView.js +17 -0
  7. package/dist/_internal/client/features/lottery/LotteryEntriesView.d.ts +23 -0
  8. package/dist/_internal/client/features/lottery/LotteryEntriesView.js +58 -0
  9. package/dist/_internal/client/features/lottery/LotteryListView.d.ts +21 -0
  10. package/dist/_internal/client/features/lottery/LotteryListView.js +25 -0
  11. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +19 -0
  12. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -0
  13. package/dist/_internal/client/features/lottery/LotterySlotGrid.d.ts +13 -0
  14. package/dist/_internal/client/features/lottery/LotterySlotGrid.js +21 -0
  15. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.d.ts +28 -0
  16. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +18 -0
  17. package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +1 -0
  18. package/dist/_internal/server/features/auctions/__tests__/service.test.js +140 -0
  19. package/dist/_internal/server/features/auctions/data.d.ts +2 -4
  20. package/dist/_internal/server/features/auctions/data.js +3 -9
  21. package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +1 -0
  22. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +600 -0
  23. package/dist/_internal/server/features/classified/adapters.d.ts +2 -15
  24. package/dist/_internal/server/features/classified/adapters.js +2 -17
  25. package/dist/_internal/server/features/classified/data.d.ts +1 -6
  26. package/dist/_internal/server/features/classified/data.js +2 -10
  27. package/dist/_internal/server/features/digital-code/adapters.d.ts +2 -15
  28. package/dist/_internal/server/features/digital-code/adapters.js +2 -17
  29. package/dist/_internal/server/features/digital-code/data.d.ts +1 -6
  30. package/dist/_internal/server/features/digital-code/data.js +2 -10
  31. package/dist/_internal/server/features/live/adapters.d.ts +2 -15
  32. package/dist/_internal/server/features/live/adapters.js +2 -17
  33. package/dist/_internal/server/features/live/data.d.ts +1 -6
  34. package/dist/_internal/server/features/live/data.js +2 -10
  35. package/dist/_internal/server/features/lottery/actions.d.ts +43 -0
  36. package/dist/_internal/server/features/lottery/actions.js +243 -0
  37. package/dist/_internal/server/features/lottery/adapters.d.ts +9 -0
  38. package/dist/_internal/server/features/lottery/adapters.js +21 -0
  39. package/dist/_internal/server/features/lottery/data.d.ts +20 -0
  40. package/dist/_internal/server/features/lottery/data.js +41 -0
  41. package/dist/_internal/server/features/lottery/metadata.d.ts +6 -0
  42. package/dist/_internal/server/features/lottery/metadata.js +31 -0
  43. package/dist/_internal/server/features/pre-orders/data.d.ts +2 -4
  44. package/dist/_internal/server/features/pre-orders/data.js +3 -9
  45. package/dist/_internal/server/features/prize-draws/actions.d.ts +2 -0
  46. package/dist/_internal/server/features/prize-draws/actions.js +22 -0
  47. package/dist/_internal/server/features/prize-draws/data.d.ts +1 -17
  48. package/dist/_internal/server/features/prize-draws/data.js +2 -20
  49. package/dist/_internal/server/features/prize-draws/index.d.ts +3 -1
  50. package/dist/_internal/server/features/prize-draws/index.js +2 -0
  51. package/dist/_internal/server/features/prize-draws/service.d.ts +3 -0
  52. package/dist/_internal/server/features/prize-draws/service.js +19 -0
  53. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +1 -0
  54. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +263 -0
  55. package/dist/_internal/server/features/shared/listing-adapters.d.ts +19 -0
  56. package/dist/_internal/server/features/shared/listing-adapters.js +20 -0
  57. package/dist/_internal/server/features/shared/listing-data-factory.d.ts +9 -0
  58. package/dist/_internal/server/features/shared/listing-data-factory.js +33 -0
  59. package/dist/_internal/server/features/stores/data.d.ts +3 -14
  60. package/dist/_internal/server/features/stores/data.js +6 -44
  61. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +1 -0
  62. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +249 -0
  63. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +1 -0
  64. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +201 -0
  65. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +1 -0
  66. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +169 -0
  67. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +1 -0
  68. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +148 -0
  69. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +1 -0
  70. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +210 -0
  71. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +1 -0
  72. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +190 -0
  73. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +1 -0
  74. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +161 -0
  75. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +1 -0
  76. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +302 -0
  77. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +1 -0
  78. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +252 -0
  79. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +1 -0
  80. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +129 -0
  81. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  82. package/dist/_internal/shared/actions/action-registry.js +46 -0
  83. package/dist/_internal/shared/features/cart/schema.d.ts +8 -8
  84. package/dist/_internal/shared/features/cart/schema.js +3 -0
  85. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  86. package/dist/_internal/shared/listing-types/_registry.js +2 -0
  87. package/dist/_internal/shared/listing-types/auction/schema.d.ts +3 -1
  88. package/dist/_internal/shared/listing-types/auction/schema.js +7 -1
  89. package/dist/_internal/shared/listing-types/classified/schema.d.ts +2 -1
  90. package/dist/_internal/shared/listing-types/classified/schema.js +3 -1
  91. package/dist/_internal/shared/listing-types/digital-code/schema.d.ts +3 -1
  92. package/dist/_internal/shared/listing-types/digital-code/schema.js +7 -1
  93. package/dist/_internal/shared/listing-types/live/schema.d.ts +2 -1
  94. package/dist/_internal/shared/listing-types/live/schema.js +3 -1
  95. package/dist/_internal/shared/listing-types/pre-order/schema.d.ts +3 -1
  96. package/dist/_internal/shared/listing-types/pre-order/schema.js +7 -1
  97. package/dist/_internal/shared/listing-types/prize-draw/schema.d.ts +3 -1
  98. package/dist/_internal/shared/listing-types/prize-draw/schema.js +13 -1
  99. package/dist/_internal/shared/listing-types/standard/schema.d.ts +2 -1
  100. package/dist/_internal/shared/listing-types/standard/schema.js +4 -1
  101. package/dist/_internal/shared/types/base-document.d.ts +15 -0
  102. package/dist/_internal/shared/types/base-document.js +1 -0
  103. package/dist/_internal/shared/types/index.d.ts +2 -0
  104. package/dist/_internal/shared/types/index.js +1 -0
  105. package/dist/client.d.ts +13 -4
  106. package/dist/client.js +11 -2
  107. package/dist/constants/api-endpoints.d.ts +12 -0
  108. package/dist/constants/api-endpoints.js +4 -0
  109. package/dist/constants/field-names.d.ts +5 -1
  110. package/dist/constants/field-names.js +5 -1
  111. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +1 -0
  112. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +386 -0
  113. package/dist/features/addresses/schemas/firestore.d.ts +2 -4
  114. package/dist/features/admin/api/bids/route.d.ts +2 -2
  115. package/dist/features/admin/api/coupons/route.d.ts +2 -2
  116. package/dist/features/admin/api/products/route.d.ts +2 -2
  117. package/dist/features/admin/api/reviews/route.d.ts +2 -2
  118. package/dist/features/admin/components/AdminFulfillmentView.d.ts +6 -0
  119. package/dist/features/admin/components/AdminFulfillmentView.js +107 -0
  120. package/dist/features/admin/components/AdminProductEditorView.js +21 -9
  121. package/dist/features/admin/components/AdminProductsView.js +3 -0
  122. package/dist/features/admin/components/DataListingView.d.ts +1 -0
  123. package/dist/features/admin/components/index.d.ts +2 -0
  124. package/dist/features/admin/components/index.js +1 -0
  125. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +1 -0
  126. package/dist/features/admin/repository/__tests__/notification.repository.test.js +356 -0
  127. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +1 -0
  128. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +298 -0
  129. package/dist/features/admin/schemas/firestore.d.ts +3 -8
  130. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +1 -0
  131. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +290 -0
  132. package/dist/features/auctions/schemas/firestore.d.ts +2 -4
  133. package/dist/features/auctions/schemas/index.d.ts +2 -2
  134. package/dist/features/auth/api/route.d.ts +2 -2
  135. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +1 -0
  136. package/dist/features/auth/repository/__tests__/session.repository.test.js +310 -0
  137. package/dist/features/auth/repository/__tests__/session.test.d.ts +1 -0
  138. package/dist/features/auth/repository/__tests__/session.test.js +146 -0
  139. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +1 -0
  140. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +171 -0
  141. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +1 -0
  142. package/dist/features/auth/repository/__tests__/sms-counter.test.js +88 -0
  143. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +1 -0
  144. package/dist/features/auth/repository/__tests__/token.repository.test.js +260 -0
  145. package/dist/features/auth/repository/__tests__/token.test.d.ts +1 -0
  146. package/dist/features/auth/repository/__tests__/token.test.js +140 -0
  147. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +1 -0
  148. package/dist/features/auth/repository/__tests__/user.repository.test.js +352 -0
  149. package/dist/features/auth/repository/__tests__/user.test.d.ts +1 -0
  150. package/dist/features/auth/repository/__tests__/user.test.js +226 -0
  151. package/dist/features/auth/repository/session.repository.js +10 -1
  152. package/dist/features/before-after/schemas/index.d.ts +2 -2
  153. package/dist/features/blog/schemas/firestore.d.ts +2 -4
  154. package/dist/features/blog/schemas/index.d.ts +4 -4
  155. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +1 -0
  156. package/dist/features/cart/repository/__tests__/cart.repository.test.js +371 -0
  157. package/dist/features/cart/repository/cart.repository.js +2 -2
  158. package/dist/features/cart/schemas/firestore.d.ts +2 -4
  159. package/dist/features/categories/api/[id]/route.d.ts +4 -4
  160. package/dist/features/categories/api/route.d.ts +2 -2
  161. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +1 -0
  162. package/dist/features/categories/repository/__tests__/categories.repository.test.js +813 -0
  163. package/dist/features/categories/schemas/firestore.d.ts +2 -4
  164. package/dist/features/categories/schemas/index.d.ts +4 -4
  165. package/dist/features/events/components/EventCard.js +1 -0
  166. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +1 -0
  167. package/dist/features/events/repository/__tests__/event.repository.test.js +299 -0
  168. package/dist/features/events/schemas/firestore.d.ts +5 -4
  169. package/dist/features/events/schemas/index.d.ts +836 -16
  170. package/dist/features/events/schemas/index.js +80 -1
  171. package/dist/features/events/types/index.d.ts +4 -1
  172. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +1 -0
  173. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +311 -0
  174. package/dist/features/faq/schemas/firestore.d.ts +2 -4
  175. package/dist/features/faq/schemas/index.d.ts +2 -2
  176. package/dist/features/grouped/schemas/index.d.ts +2 -2
  177. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +1 -0
  178. package/dist/features/history/repository/__tests__/user-history.repository.test.js +180 -0
  179. package/dist/features/homepage/api/[id]/route.d.ts +4 -4
  180. package/dist/features/homepage/api/carousel/[id]/route.d.ts +4 -4
  181. package/dist/features/homepage/api/carousel/route.d.ts +2 -2
  182. package/dist/features/homepage/api/route.d.ts +2 -2
  183. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +1 -0
  184. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +182 -0
  185. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +1 -0
  186. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +185 -0
  187. package/dist/features/homepage/schemas/firestore.d.ts +4 -12
  188. package/dist/features/homepage/schemas/index.d.ts +2 -2
  189. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +33 -0
  190. package/dist/features/lottery/repository/lottery-entry.repository.js +130 -0
  191. package/dist/features/lottery/schemas/firestore.d.ts +49 -0
  192. package/dist/features/lottery/schemas/firestore.js +25 -0
  193. package/dist/features/lottery/schemas/zod.d.ts +113 -0
  194. package/dist/features/lottery/schemas/zod.js +39 -0
  195. package/dist/features/lottery/types/index.d.ts +67 -0
  196. package/dist/features/lottery/types/index.js +55 -0
  197. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +1 -0
  198. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +257 -0
  199. package/dist/features/messages/schemas/firestore.d.ts +2 -4
  200. package/dist/features/messages/schemas/index.d.ts +2 -2
  201. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +1 -0
  202. package/dist/features/orders/repository/__tests__/orders.repository.test.js +211 -0
  203. package/dist/features/orders/repository/orders.repository.d.ts +5 -0
  204. package/dist/features/orders/repository/orders.repository.js +26 -0
  205. package/dist/features/orders/schemas/firestore.d.ts +9 -5
  206. package/dist/features/orders/schemas/firestore.js +3 -0
  207. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +1 -0
  208. package/dist/features/payments/repository/__tests__/payout.repository.test.js +292 -0
  209. package/dist/features/payments/schemas/firestore.d.ts +2 -4
  210. package/dist/features/pre-orders/schemas/index.d.ts +2 -2
  211. package/dist/features/products/api/[id]/route.d.ts +4 -4
  212. package/dist/features/products/api/route.d.ts +2 -2
  213. package/dist/features/products/constants/action-defs.d.ts +16 -0
  214. package/dist/features/products/constants/action-defs.js +16 -0
  215. package/dist/features/products/constants/listing-tabs.d.ts +48 -0
  216. package/dist/features/products/constants/listing-tabs.js +12 -0
  217. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +1 -0
  218. package/dist/features/products/repository/__tests__/product-features.repository.test.js +329 -0
  219. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +1 -0
  220. package/dist/features/products/repository/__tests__/products.repository.test.js +607 -0
  221. package/dist/features/products/repository/products.repository.d.ts +37 -0
  222. package/dist/features/products/repository/products.repository.js +28 -1
  223. package/dist/features/products/schemas/firestore.d.ts +23 -7
  224. package/dist/features/products/schemas/firestore.js +2 -0
  225. package/dist/features/products/schemas/index.d.ts +18 -18
  226. package/dist/features/products/schemas/index.js +4 -2
  227. package/dist/features/products/types/index.d.ts +3 -1
  228. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +1 -0
  229. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +219 -0
  230. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +1 -0
  231. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +480 -0
  232. package/dist/features/promotions/schemas/firestore.d.ts +2 -4
  233. package/dist/features/promotions/schemas/index.d.ts +4 -4
  234. package/dist/features/reviews/api/[id]/route.d.ts +4 -4
  235. package/dist/features/reviews/api/route.d.ts +2 -2
  236. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +1 -0
  237. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +327 -0
  238. package/dist/features/reviews/schemas/firestore.d.ts +2 -4
  239. package/dist/features/reviews/schemas/index.d.ts +2 -2
  240. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +1 -0
  241. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +385 -0
  242. package/dist/features/scams/schemas/firestore.d.ts +2 -4
  243. package/dist/features/scams/schemas/index.d.ts +4 -4
  244. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +1 -0
  245. package/dist/features/search/repository/__tests__/search.repository.test.js +369 -0
  246. package/dist/features/search/schemas/index.d.ts +2 -2
  247. package/dist/features/seller/api/coupons/route.d.ts +2 -2
  248. package/dist/features/seller/api/offers/route.d.ts +2 -2
  249. package/dist/features/seller/api/products/route.d.ts +2 -2
  250. package/dist/features/seller/api/store/route.d.ts +2 -2
  251. package/dist/features/seller/components/BarcodeField.d.ts +17 -0
  252. package/dist/features/seller/components/BarcodeField.js +30 -0
  253. package/dist/features/seller/components/FulfillmentView.d.ts +5 -0
  254. package/dist/features/seller/components/FulfillmentView.js +120 -0
  255. package/dist/features/seller/components/PrintCenterView.d.ts +3 -1
  256. package/dist/features/seller/components/PrintCenterView.js +52 -4
  257. package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
  258. package/dist/features/seller/components/SellerProductShell.js +2 -1
  259. package/dist/features/seller/components/index.d.ts +4 -0
  260. package/dist/features/seller/components/index.js +2 -0
  261. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +1 -0
  262. package/dist/features/seller/repository/__tests__/offer.repository.test.js +458 -0
  263. package/dist/features/seller/schemas/index.d.ts +2 -2
  264. package/dist/features/store-extensions/schemas/firestore.d.ts +12 -44
  265. package/dist/features/stores/components/StoreClassifiedsListing.d.ts +5 -0
  266. package/dist/features/stores/components/StoreClassifiedsListing.js +48 -0
  267. package/dist/features/stores/components/StoreClassifiedsPageView.d.ts +4 -0
  268. package/dist/features/stores/components/StoreClassifiedsPageView.js +20 -0
  269. package/dist/features/stores/components/StoreDetailLayoutView.js +23 -2
  270. package/dist/features/stores/components/StoreDigitalCodesListing.d.ts +5 -0
  271. package/dist/features/stores/components/StoreDigitalCodesListing.js +48 -0
  272. package/dist/features/stores/components/StoreDigitalCodesPageView.d.ts +4 -0
  273. package/dist/features/stores/components/StoreDigitalCodesPageView.js +20 -0
  274. package/dist/features/stores/components/StoreLiveItemsListing.d.ts +5 -0
  275. package/dist/features/stores/components/StoreLiveItemsListing.js +48 -0
  276. package/dist/features/stores/components/StoreLiveItemsPageView.d.ts +4 -0
  277. package/dist/features/stores/components/StoreLiveItemsPageView.js +20 -0
  278. package/dist/features/stores/components/index.d.ts +9 -0
  279. package/dist/features/stores/components/index.js +3 -0
  280. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +1 -0
  281. package/dist/features/stores/repository/__tests__/store.repository.test.js +261 -0
  282. package/dist/features/stores/schemas/firestore.d.ts +2 -4
  283. package/dist/features/stores/schemas/index.d.ts +4 -4
  284. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +1 -0
  285. package/dist/features/support/repository/__tests__/support.repository.test.js +312 -0
  286. package/dist/features/support/schemas/firestore.d.ts +2 -4
  287. package/dist/features/support/schemas/index.d.ts +2 -2
  288. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +1 -0
  289. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +139 -0
  290. package/dist/index.d.ts +14 -0
  291. package/dist/index.js +17 -0
  292. package/dist/next/api/routeHandler.d.ts +1 -1
  293. package/dist/next/routing/route-map.d.ts +24 -0
  294. package/dist/next/routing/route-map.js +11 -0
  295. package/dist/repositories/index.d.ts +1 -0
  296. package/dist/repositories/index.js +2 -0
  297. package/dist/schemas/registry.d.ts +24 -24
  298. package/dist/security/index.d.ts +1 -1
  299. package/dist/security/index.js +1 -1
  300. package/dist/security/pii-schemas.d.ts +2 -0
  301. package/dist/security/pii-schemas.js +6 -0
  302. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  303. package/dist/seed/events-seed-data.js +85 -2
  304. package/dist/seed/grouped-listings-seed-data.d.ts +5 -2
  305. package/dist/seed/index.d.ts +1 -0
  306. package/dist/seed/index.js +1 -0
  307. package/dist/seed/lottery-entries-seed-data.d.ts +2 -0
  308. package/dist/seed/lottery-entries-seed-data.js +108 -0
  309. package/dist/seed/manifest.js +1 -0
  310. package/dist/seed/products-preorders-seed-data.d.ts +5 -2
  311. package/dist/seed/products-standard-seed-data.js +8 -0
  312. package/dist/server-entry.d.ts +3 -0
  313. package/dist/server-entry.js +3 -0
  314. package/dist/server.d.ts +10 -4
  315. package/dist/server.js +6 -0
  316. package/dist/styles.css +1 -1
  317. package/dist/tailwind-utilities.css +1 -1
  318. package/dist/utils/id-generators.d.ts +8 -0
  319. package/dist/utils/id-generators.js +14 -0
  320. package/package.json +2 -1
@@ -1,21 +1,8 @@
1
1
  import type { ProductDocument, ProductDigitalCodeMeta } from "../../../../features/products/schemas/firestore";
2
- export interface DigitalCodeClientShape {
3
- id: string;
4
- title: string;
5
- description: string;
6
- price: number;
7
- priceLabel: string;
8
- currency: string;
9
- mainImage: string | null;
10
- images: string[];
11
- storeId: string;
12
- storeName: string | null;
13
- category: string;
14
- tags: string[];
2
+ import { type BaseListingClientShape } from "../shared/listing-adapters";
3
+ export interface DigitalCodeClientShape extends BaseListingClientShape {
15
4
  /** Delivery method and redemption instructions — codesAvailable intentionally omitted (operational). */
16
5
  digitalCode: Pick<ProductDigitalCodeMeta, "codeDeliveryMethod" | "redemptionInstructions"> | null;
17
- status: ProductDocument["status"];
18
- createdAt: string;
19
6
  }
20
7
  /** Maps a raw `ProductDocument` to the client-safe digital-code shape. Strips codesAvailable/codePoolSize (operational counters). */
21
8
  export declare function toClientDigitalCode(doc: ProductDocument): DigitalCodeClientShape;
@@ -1,29 +1,14 @@
1
- import { formatCurrency } from "../../../../utils/number.formatter";
1
+ import { mapBaseListingFields } from "../shared/listing-adapters";
2
2
  /** Maps a raw `ProductDocument` to the client-safe digital-code shape. Strips codesAvailable/codePoolSize (operational counters). */
3
3
  export function toClientDigitalCode(doc) {
4
4
  const dc = doc.digitalCode ?? null;
5
5
  return {
6
- id: doc.id,
7
- title: doc.title,
8
- description: doc.description,
9
- price: doc.price,
10
- priceLabel: formatCurrency(doc.price, doc.currency ?? "INR"),
11
- currency: doc.currency ?? "INR",
12
- mainImage: doc.mainImage || doc.images?.[0] || null,
13
- images: doc.images ?? [],
14
- storeId: doc.storeId,
15
- storeName: doc.storeName ?? null,
16
- category: doc.categorySlugs?.[0] ?? doc.category ?? "",
17
- tags: doc.tags ?? [],
6
+ ...mapBaseListingFields(doc),
18
7
  digitalCode: dc
19
8
  ? {
20
9
  codeDeliveryMethod: dc.codeDeliveryMethod,
21
10
  redemptionInstructions: dc.redemptionInstructions,
22
11
  }
23
12
  : null,
24
- status: doc.status,
25
- createdAt: doc.createdAt instanceof Date
26
- ? doc.createdAt.toISOString()
27
- : String(doc.createdAt),
28
13
  };
29
14
  }
@@ -1,6 +1 @@
1
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
2
- export interface DigitalCodeDataOptions {
3
- _reserved?: never;
4
- }
5
- /** Fetch a single digital-code listing by slug, deduped per RSC render. */
6
- export declare const getDigitalCodeForDetail: (slug: string, _opts?: DigitalCodeDataOptions) => Promise<ProductDocument | null>;
1
+ export declare const getDigitalCodeForDetail: (slugOrId: string) => Promise<import("../../../..").ProductDocument | null>;
@@ -1,10 +1,2 @@
1
- import { cache } from "react";
2
- import { productRepository } from "../../../../repositories";
3
- /** Fetch a single digital-code listing by slug, deduped per RSC render. */
4
- export const getDigitalCodeForDetail = cache(async (slug, _opts) => {
5
- void _opts;
6
- const product = await productRepository.findByIdOrSlug(slug).catch(() => undefined);
7
- if (!product || product.listingType !== "digital-code")
8
- return null;
9
- return product;
10
- });
1
+ import { makeGetListingForDetail } from "../shared/listing-data-factory";
2
+ export const getDigitalCodeForDetail = makeGetListingForDetail("digital-code");
@@ -1,21 +1,8 @@
1
1
  import type { ProductDocument, ProductLiveItemMeta } from "../../../../features/products/schemas/firestore";
2
- export interface LiveItemClientShape {
3
- id: string;
4
- title: string;
5
- description: string;
6
- price: number;
7
- priceLabel: string;
8
- currency: string;
9
- mainImage: string | null;
10
- images: string[];
11
- storeId: string;
12
- storeName: string | null;
13
- category: string;
14
- tags: string[];
2
+ import { type BaseListingClientShape } from "../shared/listing-adapters";
3
+ export interface LiveItemClientShape extends BaseListingClientShape {
15
4
  /** Live-item meta — vendorVerified is intentionally omitted (admin-only). */
16
5
  liveItem: Omit<ProductLiveItemMeta, "vendorVerified"> | null;
17
- status: ProductDocument["status"];
18
- createdAt: string;
19
6
  }
20
7
  /** Maps a raw `ProductDocument` to the client-safe live-item shape. Strips vendorVerified (admin-only). */
21
8
  export declare function toClientLiveItem(doc: ProductDocument): LiveItemClientShape;
@@ -1,20 +1,9 @@
1
- import { formatCurrency } from "../../../../utils/number.formatter";
1
+ import { mapBaseListingFields } from "../shared/listing-adapters";
2
2
  /** Maps a raw `ProductDocument` to the client-safe live-item shape. Strips vendorVerified (admin-only). */
3
3
  export function toClientLiveItem(doc) {
4
4
  const li = doc.liveItem ?? null;
5
5
  return {
6
- id: doc.id,
7
- title: doc.title,
8
- description: doc.description,
9
- price: doc.price,
10
- priceLabel: formatCurrency(doc.price, doc.currency ?? "INR"),
11
- currency: doc.currency ?? "INR",
12
- mainImage: doc.mainImage || doc.images?.[0] || null,
13
- images: doc.images ?? [],
14
- storeId: doc.storeId,
15
- storeName: doc.storeName ?? null,
16
- category: doc.categorySlugs?.[0] ?? doc.category ?? "",
17
- tags: doc.tags ?? [],
6
+ ...mapBaseListingFields(doc),
18
7
  liveItem: li
19
8
  ? {
20
9
  species: li.species,
@@ -26,9 +15,5 @@ export function toClientLiveItem(doc) {
26
15
  cites: li.cites,
27
16
  }
28
17
  : null,
29
- status: doc.status,
30
- createdAt: doc.createdAt instanceof Date
31
- ? doc.createdAt.toISOString()
32
- : String(doc.createdAt),
33
18
  };
34
19
  }
@@ -1,6 +1 @@
1
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
2
- export interface LiveDataOptions {
3
- _reserved?: never;
4
- }
5
- /** Fetch a single live-item listing by slug, deduped per RSC render. */
6
- export declare const getLiveItemForDetail: (slug: string, _opts?: LiveDataOptions) => Promise<ProductDocument | null>;
1
+ export declare const getLiveItemForDetail: (slugOrId: string) => Promise<import("../../../..").ProductDocument | null>;
@@ -1,10 +1,2 @@
1
- import { cache } from "react";
2
- import { productRepository } from "../../../../repositories";
3
- /** Fetch a single live-item listing by slug, deduped per RSC render. */
4
- export const getLiveItemForDetail = cache(async (slug, _opts) => {
5
- void _opts;
6
- const product = await productRepository.findByIdOrSlug(slug).catch(() => undefined);
7
- if (!product || product.listingType !== "live")
8
- return null;
9
- return product;
10
- });
1
+ import { makeGetListingForDetail } from "../shared/listing-data-factory";
2
+ export const getLiveItemForDetail = makeGetListingForDetail("live");
@@ -0,0 +1,43 @@
1
+ import { type ActionResult } from "@mohasinac/appkit/server";
2
+ import type { LotteryConfig } from "../../../../features/lottery/types";
3
+ import type { LotteryEntryDocument } from "../../../../features/lottery/schemas/firestore";
4
+ /**
5
+ * User-initiated lottery pull.
6
+ * Atomically:
7
+ * 1. Validates inputs + limits
8
+ * 2. Runs weighted slot selection on unclaimed slots
9
+ * 3. Marks the slot as booked
10
+ * 4. Creates the LotteryEntryDocument with assignedPrizeSlotNumber set
11
+ *
12
+ * Returns the assigned slot number so the user sees their prize immediately.
13
+ */
14
+ export declare function submitLotteryPullAction(input: unknown): Promise<ActionResult<{
15
+ userLotteryNumber: number;
16
+ assignedPrizeSlotNumber: number;
17
+ slotName: string;
18
+ }>>;
19
+ /**
20
+ * Admin — flag a lottery entry as fraudulent.
21
+ * Slot stays booked; use reopenLotterySlotAction to free it.
22
+ */
23
+ export declare function flagLotteryEntryAction(input: unknown): Promise<ActionResult<LotteryEntryDocument>>;
24
+ /**
25
+ * Admin — reopen a slot from a flagged entry.
26
+ * Clears isBooked on the slot so it can be claimed in a future pull.
27
+ */
28
+ export declare function reopenLotterySlotAction(input: unknown): Promise<ActionResult<void>>;
29
+ /**
30
+ * Admin — create a new lottery event.
31
+ * Weights computed server-side; never returned to client.
32
+ */
33
+ export declare function createLotteryEventAction(data: unknown): Promise<ActionResult<unknown>>;
34
+ /**
35
+ * Admin — update a lottery event.
36
+ * Recomputes slot weights after update.
37
+ */
38
+ export declare function updateLotteryEventAction(id: string, data: unknown): Promise<ActionResult<unknown>>;
39
+ /**
40
+ * Store owner or Admin — switch a prize-draw product into lottery mode.
41
+ * Store owners provide prizeSlotPrice but weight is NEVER returned to them.
42
+ */
43
+ export declare function setProductLotteryModeAction(productId: string, lotteryConfig: LotteryConfig): Promise<ActionResult<void>>;
@@ -0,0 +1,243 @@
1
+ "use server";
2
+ import { wrapAction } from "@mohasinac/appkit/server";
3
+ import { getAdminDb } from "../../../../providers/db-firebase";
4
+ import { eventRepository } from "../../../../repositories";
5
+ import { lotteryEntryRepository } from "../../../../features/lottery/repository/lottery-entry.repository";
6
+ import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
7
+ import { ValidationError } from "../../../shared/errors/index";
8
+ import { submitLotteryPullSchema, flagLotteryEntrySchema, reopenLotterySlotSchema, } from "../../../../features/lottery/schemas/zod";
9
+ import { LotteryError, assignSlotWeights, pickWeightedSlot, } from "../../../../features/lottery/types";
10
+ import { LOTTERY_ENTRIES_COLLECTION } from "../../../../features/lottery/schemas/firestore";
11
+ // ── Helpers ──────────────────────────────────────────────────────────────────
12
+ function isDrawWindowOpen(config) {
13
+ // Draw window is implicitly open when there are unclaimed slots.
14
+ // A real implementation would also check if the event status is "active".
15
+ return config.slots.some((s) => !s.isBooked);
16
+ }
17
+ // ── Public actions ────────────────────────────────────────────────────────────
18
+ /**
19
+ * User-initiated lottery pull.
20
+ * Atomically:
21
+ * 1. Validates inputs + limits
22
+ * 2. Runs weighted slot selection on unclaimed slots
23
+ * 3. Marks the slot as booked
24
+ * 4. Creates the LotteryEntryDocument with assignedPrizeSlotNumber set
25
+ *
26
+ * Returns the assigned slot number so the user sees their prize immediately.
27
+ */
28
+ export async function submitLotteryPullAction(input) {
29
+ return wrapAction(async () => {
30
+ // Auth — must be logged in
31
+ const user = await requireRoleUser(["buyer", "seller", "admin", "moderator", "employee"]);
32
+ const parsed = submitLotteryPullSchema.safeParse(input);
33
+ if (!parsed.success) {
34
+ throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid lottery pull input");
35
+ }
36
+ const data = parsed.data;
37
+ const sourceId = data.sourceType === "event" ? data.eventId : data.productId;
38
+ const sourceField = data.sourceType === "event" ? "eventId" : "productId";
39
+ // Load the event/product to get the lotteryConfig
40
+ let lotteryConfig;
41
+ if (data.sourceType === "event") {
42
+ const event = await eventRepository.findById(sourceId).catch(() => null);
43
+ if (!event || event.type !== "lottery") {
44
+ throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Lottery event not found or not of type lottery.");
45
+ }
46
+ if (event.status !== "active") {
47
+ throw new LotteryError("LOTTERY_WINDOW_CLOSED", "This lottery is not currently active.");
48
+ }
49
+ if (!event.lotteryConfig) {
50
+ throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Lottery config not found on event.");
51
+ }
52
+ lotteryConfig = event.lotteryConfig;
53
+ }
54
+ else {
55
+ // Product lottery — load via product repository (not implemented here; caller ensures correct source)
56
+ throw new ValidationError("Product lottery pull must go through the product lottery pull route.");
57
+ }
58
+ // Compute weights
59
+ const weightedSlots = assignSlotWeights(lotteryConfig);
60
+ // Check draw window
61
+ if (!isDrawWindowOpen(lotteryConfig)) {
62
+ throw new LotteryError("LOTTERY_FULL", "All slots have been claimed.");
63
+ }
64
+ // Enforce maxPullsPerUser
65
+ const existingUserPulls = await lotteryEntryRepository.countByUser(sourceId, sourceField, user.uid);
66
+ if (existingUserPulls >= lotteryConfig.maxPullsPerUser) {
67
+ throw new LotteryError("USER_LIMIT_REACHED", "You have reached the maximum number of pulls for this lottery.");
68
+ }
69
+ // Enforce maxPullsPerTransaction
70
+ const existingTxPulls = await lotteryEntryRepository.countByTransactionId(sourceId, sourceField, data.transactionId);
71
+ if (existingTxPulls >= lotteryConfig.maxPullsPerTransaction) {
72
+ throw new LotteryError("TX_ALREADY_USED", "This transaction ID has already been used the maximum number of times.");
73
+ }
74
+ // Atomically: pick slot + create entry + mark slot booked
75
+ const db = getAdminDb();
76
+ const sourceDocRef = db.collection("events").doc(sourceId);
77
+ const { assignedSlot, userLotteryNumber } = await db.runTransaction(async (tx) => {
78
+ // Re-read lotteryConfig inside transaction for freshness
79
+ const sourceSnap = await tx.get(sourceDocRef);
80
+ if (!sourceSnap.exists)
81
+ throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Lottery source not found.");
82
+ const freshConfig = sourceSnap.data().lotteryConfig;
83
+ if (!freshConfig)
84
+ throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Lottery config missing.");
85
+ const freshWeighted = assignSlotWeights(freshConfig);
86
+ const unclaimed = freshWeighted.filter((s) => !s.isBooked);
87
+ if (unclaimed.length === 0)
88
+ throw new LotteryError("LOTTERY_FULL", "All slots have been claimed.");
89
+ // Weighted pick
90
+ const chosen = pickWeightedSlot(unclaimed);
91
+ // Compute next userLotteryNumber (count + 1 inside tx via collection size)
92
+ const countSnap = await db
93
+ .collection(LOTTERY_ENTRIES_COLLECTION)
94
+ .where(sourceField, "==", sourceId)
95
+ .get();
96
+ const nextNumber = countSnap.size + 1;
97
+ // Mark slot booked in the source document
98
+ const updatedSlots = freshConfig.slots.map((s) => s.slotNumber === chosen.slotNumber
99
+ ? {
100
+ ...s,
101
+ isBooked: true,
102
+ bookedByUserId: user.uid,
103
+ bookedByDisplayName: user.displayName ?? user.name ?? undefined,
104
+ bookedByUserLotteryNumber: nextNumber,
105
+ }
106
+ : s);
107
+ tx.update(sourceDocRef, {
108
+ "lotteryConfig.slots": updatedSlots,
109
+ });
110
+ return { assignedSlot: chosen, userLotteryNumber: nextNumber };
111
+ });
112
+ // Create the entry document outside the transaction (acceptable — slot is already booked)
113
+ const entryData = {
114
+ sourceType: data.sourceType,
115
+ ...(data.sourceType === "event" ? { eventId: sourceId } : { productId: sourceId }),
116
+ userId: user.uid,
117
+ userDisplayName: user.displayName ?? user.name ?? undefined,
118
+ userEmail: user.email ?? undefined,
119
+ userPhone: data.userPhone,
120
+ transactionId: data.transactionId,
121
+ paymentTime: new Date(data.paymentTime),
122
+ purchasedItemNumber: data.purchasedItemNumber,
123
+ userLotteryNumber,
124
+ assignedPrizeSlotNumber: assignedSlot.slotNumber,
125
+ status: "drawn",
126
+ isFlagged: false,
127
+ submittedAt: new Date(),
128
+ drawnAt: new Date(),
129
+ };
130
+ await lotteryEntryRepository.createEntry(entryData);
131
+ return {
132
+ userLotteryNumber,
133
+ assignedPrizeSlotNumber: assignedSlot.slotNumber,
134
+ slotName: assignedSlot.name,
135
+ };
136
+ });
137
+ }
138
+ /**
139
+ * Admin — flag a lottery entry as fraudulent.
140
+ * Slot stays booked; use reopenLotterySlotAction to free it.
141
+ */
142
+ export async function flagLotteryEntryAction(input) {
143
+ return wrapAction(async () => {
144
+ await requireRoleUser(["admin", "moderator"]);
145
+ const parsed = flagLotteryEntrySchema.safeParse(input);
146
+ if (!parsed.success) {
147
+ throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid flag input");
148
+ }
149
+ return lotteryEntryRepository.flagEntry(parsed.data.entryId, parsed.data.flagNote, parsed.data.flaggedByUserId);
150
+ });
151
+ }
152
+ /**
153
+ * Admin — reopen a slot from a flagged entry.
154
+ * Clears isBooked on the slot so it can be claimed in a future pull.
155
+ */
156
+ export async function reopenLotterySlotAction(input) {
157
+ return wrapAction(async () => {
158
+ await requireRoleUser(["admin"]);
159
+ const parsed = reopenLotterySlotSchema.safeParse(input);
160
+ if (!parsed.success) {
161
+ throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid reopen input");
162
+ }
163
+ const { sourceType, sourceId, slotNumber } = parsed.data;
164
+ const db = getAdminDb();
165
+ const collectionName = sourceType === "event" ? "events" : "products";
166
+ const docRef = db.collection(collectionName).doc(sourceId);
167
+ await db.runTransaction(async (tx) => {
168
+ const snap = await tx.get(docRef);
169
+ if (!snap.exists)
170
+ throw new ValidationError("Source document not found.");
171
+ const config = snap.data().lotteryConfig;
172
+ if (!config?.slots)
173
+ throw new ValidationError("Lottery config not found.");
174
+ const updatedSlots = config.slots.map((s) => s.slotNumber === slotNumber
175
+ ? {
176
+ ...s,
177
+ isBooked: false,
178
+ bookedByUserId: null,
179
+ bookedByDisplayName: null,
180
+ bookedByUserLotteryNumber: null,
181
+ }
182
+ : s);
183
+ tx.update(docRef, { "lotteryConfig.slots": updatedSlots });
184
+ });
185
+ });
186
+ }
187
+ /**
188
+ * Admin — create a new lottery event.
189
+ * Weights computed server-side; never returned to client.
190
+ */
191
+ export async function createLotteryEventAction(data) {
192
+ return wrapAction(async () => {
193
+ const user = await requireRoleUser(["admin", "moderator"]);
194
+ const rawData = data;
195
+ const lotteryConfig = rawData.lotteryConfig;
196
+ if (!lotteryConfig)
197
+ throw new ValidationError("lotteryConfig is required for lottery events.");
198
+ // Compute weights server-side
199
+ const withWeights = assignSlotWeights(lotteryConfig);
200
+ return eventRepository.createEvent({
201
+ ...rawData,
202
+ type: "lottery",
203
+ lotteryConfig: { ...lotteryConfig, slots: withWeights },
204
+ createdBy: user.uid,
205
+ status: rawData.status ?? "draft",
206
+ stats: { totalEntries: 0, approvedEntries: 0, flaggedEntries: 0 },
207
+ });
208
+ });
209
+ }
210
+ /**
211
+ * Admin — update a lottery event.
212
+ * Recomputes slot weights after update.
213
+ */
214
+ export async function updateLotteryEventAction(id, data) {
215
+ return wrapAction(async () => {
216
+ await requireRoleUser(["admin", "moderator"]);
217
+ const rawData = data;
218
+ const lotteryConfig = rawData.lotteryConfig;
219
+ if (lotteryConfig) {
220
+ const withWeights = assignSlotWeights(lotteryConfig);
221
+ return eventRepository.updateEvent(id, {
222
+ ...rawData,
223
+ lotteryConfig: { ...lotteryConfig, slots: withWeights },
224
+ });
225
+ }
226
+ return eventRepository.updateEvent(id, rawData);
227
+ });
228
+ }
229
+ /**
230
+ * Store owner or Admin — switch a prize-draw product into lottery mode.
231
+ * Store owners provide prizeSlotPrice but weight is NEVER returned to them.
232
+ */
233
+ export async function setProductLotteryModeAction(productId, lotteryConfig) {
234
+ return wrapAction(async () => {
235
+ await requireRoleUser(["admin", "moderator", "seller"]);
236
+ const withWeights = assignSlotWeights(lotteryConfig);
237
+ const db = getAdminDb();
238
+ await db.collection("products").doc(productId).update({
239
+ prizeDrawMode: "lottery",
240
+ lotteryConfig: { ...lotteryConfig, slots: withWeights },
241
+ });
242
+ });
243
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Lottery adapters — strips server-only fields (priceInPaise, weight)
3
+ * before any slot/config data leaves the server.
4
+ */
5
+ import type { LotteryConfig, LotterySlot, ClientLotteryConfig, ClientLotterySlot } from "../../../../features/lottery/types";
6
+ /** Strip priceInPaise and weight from a single slot for client consumption. */
7
+ export declare function toClientLotterySlot(slot: LotterySlot): ClientLotterySlot;
8
+ /** Strip price/weight from the entire config for client consumption. */
9
+ export declare function toClientLotteryConfig(config: LotteryConfig): ClientLotteryConfig;
@@ -0,0 +1,21 @@
1
+ /** Strip priceInPaise and weight from a single slot for client consumption. */
2
+ export function toClientLotterySlot(slot) {
3
+ return {
4
+ slotNumber: slot.slotNumber,
5
+ name: slot.name,
6
+ isBooked: slot.isBooked,
7
+ bookedByUserLotteryNumber: slot.bookedByUserLotteryNumber,
8
+ bookedByDisplayName: slot.bookedByDisplayName,
9
+ };
10
+ }
11
+ /** Strip price/weight from the entire config for client consumption. */
12
+ export function toClientLotteryConfig(config) {
13
+ return {
14
+ slots: config.slots.map(toClientLotterySlot),
15
+ totalSlots: config.totalSlots,
16
+ pricingMode: config.pricingMode,
17
+ drawWindowDurationMinutes: config.drawWindowDurationMinutes,
18
+ maxPullsPerTransaction: config.maxPullsPerTransaction,
19
+ maxPullsPerUser: config.maxPullsPerUser,
20
+ };
21
+ }
@@ -0,0 +1,20 @@
1
+ import type { SieveModel } from "../../../../providers/db-firebase";
2
+ import type { EventDocument } from "../../../../features/events/schemas/firestore";
3
+ import type { LotteryEntryDocument } from "../../../../features/lottery/schemas/firestore";
4
+ import type { ClientLotteryConfig } from "../../../../features/lottery/types";
5
+ /** Event shape with lottery config stripped of price/weight. */
6
+ export type LotteryEventClient = Omit<EventDocument, "lotteryConfig"> & {
7
+ lotteryConfig?: ClientLotteryConfig;
8
+ };
9
+ /** Fetch a lottery-type event with price/weight stripped for client use. */
10
+ export declare const getLotteryEventCached: (id: string) => Promise<LotteryEventClient | null>;
11
+ /** List all lottery-type events with price/weight stripped. */
12
+ export declare const listLotteryEvents: (opts?: {
13
+ status?: string;
14
+ page?: number;
15
+ pageSize?: number;
16
+ }) => Promise<LotteryEventClient[]>;
17
+ /** Fetch lottery entries for admin view (includes phone + txId via PII decrypt). */
18
+ export declare function getLotteryEntriesForAdmin(sourceType: "event" | "product", sourceId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
19
+ /** Fetch lottery entries for a specific user (own entries only). */
20
+ export declare function getLotteryEntriesForUser(userId: string, model: SieveModel): Promise<import("../../../..").FirebaseSieveResult<LotteryEntryDocument>>;
@@ -0,0 +1,41 @@
1
+ import { cache } from "react";
2
+ import { eventRepository } from "../../../../repositories";
3
+ import { lotteryEntryRepository } from "../../../../features/lottery/repository/lottery-entry.repository";
4
+ import { toClientLotteryConfig } from "./adapters";
5
+ /** Fetch a lottery-type event with price/weight stripped for client use. */
6
+ export const getLotteryEventCached = cache(async (id) => {
7
+ const event = await eventRepository.findById(id).catch(() => null);
8
+ if (!event || event.type !== "lottery")
9
+ return null;
10
+ return {
11
+ ...event,
12
+ lotteryConfig: event.lotteryConfig ? toClientLotteryConfig(event.lotteryConfig) : undefined,
13
+ };
14
+ });
15
+ /** List all lottery-type events with price/weight stripped. */
16
+ export const listLotteryEvents = cache(async (opts) => {
17
+ // Build Sieve filter: type==lottery, optionally also status
18
+ let filters = "type==lottery";
19
+ if (opts?.status)
20
+ filters += `,status==${opts.status}`;
21
+ const result = await eventRepository.list({
22
+ filters,
23
+ sorts: "-startsAt",
24
+ page: opts?.page ?? 1,
25
+ pageSize: opts?.pageSize ?? 50,
26
+ });
27
+ const items = result.items ?? [];
28
+ return items.map((event) => ({
29
+ ...event,
30
+ lotteryConfig: event.lotteryConfig ? toClientLotteryConfig(event.lotteryConfig) : undefined,
31
+ }));
32
+ });
33
+ /** Fetch lottery entries for admin view (includes phone + txId via PII decrypt). */
34
+ export async function getLotteryEntriesForAdmin(sourceType, sourceId, model) {
35
+ const field = sourceType === "event" ? "eventId" : "productId";
36
+ return lotteryEntryRepository.listForSource(sourceId, field, model);
37
+ }
38
+ /** Fetch lottery entries for a specific user (own entries only). */
39
+ export async function getLotteryEntriesForUser(userId, model) {
40
+ return lotteryEntryRepository.listForUser(userId, model);
41
+ }
@@ -0,0 +1,6 @@
1
+ import type { Metadata } from "next";
2
+ import type { LotteryEventClient } from "./data";
3
+ export declare function buildLotteryMetadata(event: LotteryEventClient | null, opts?: {
4
+ siteName?: string;
5
+ baseUrl?: string;
6
+ }): Metadata;
@@ -0,0 +1,31 @@
1
+ export function buildLotteryMetadata(event, opts) {
2
+ if (!event) {
3
+ return {
4
+ title: "Lottery Not Found",
5
+ description: "This lottery no longer exists.",
6
+ };
7
+ }
8
+ const siteName = opts?.siteName ?? "the platform";
9
+ const title = `${event.title} — ${siteName} Lottery`;
10
+ const description = typeof event.description === "string" && event.description.length > 0
11
+ ? event.description.slice(0, 155)
12
+ : `Enter the ${event.title} lottery on ${siteName}.`;
13
+ const coverUrl = event.coverImage && typeof event.coverImage.url === "string"
14
+ ? event.coverImage.url
15
+ : event.coverImageUrl;
16
+ return {
17
+ title,
18
+ description,
19
+ openGraph: {
20
+ title,
21
+ description,
22
+ ...(coverUrl ? { images: [{ url: coverUrl }] } : {}),
23
+ },
24
+ twitter: {
25
+ card: "summary_large_image",
26
+ title,
27
+ description,
28
+ ...(coverUrl ? { images: [coverUrl] } : {}),
29
+ },
30
+ };
31
+ }
@@ -1,4 +1,2 @@
1
- import type { ProductDocument } from "../../../../features/products/schemas/firestore";
2
- import type { ProductFeatureDocument } from "../../../../features/products/schemas/product-features";
3
- export declare const getPreOrderForDetail: (slugOrId: string) => Promise<ProductDocument | null>;
4
- export declare const getProductFeaturesForPreOrder: (storeId: string | null) => Promise<ProductFeatureDocument[]>;
1
+ export declare const getPreOrderForDetail: (slugOrId: string) => Promise<import("../../../..").ProductDocument | null>;
2
+ export declare const getProductFeaturesForPreOrder: (storeId: string | null) => Promise<import("../../../..").ProductFeatureDocument[]>;
@@ -1,9 +1,3 @@
1
- import { cache } from "react";
2
- import { productRepository } from "../../../../repositories";
3
- import { loadProductFeaturesForStore } from "../../../../features/products/repository/loadProductFeatures";
4
- export const getPreOrderForDetail = cache(async (slugOrId) => {
5
- return (await productRepository.findByIdOrSlug(slugOrId).catch(() => undefined)) ?? null;
6
- });
7
- export const getProductFeaturesForPreOrder = cache(async (storeId) => {
8
- return loadProductFeaturesForStore(storeId).catch(() => []);
9
- });
1
+ import { makeGetListingForDetail, getProductFeaturesForStore } from "../shared/listing-data-factory";
2
+ export const getPreOrderForDetail = makeGetListingForDetail("pre-order");
3
+ export const getProductFeaturesForPreOrder = getProductFeaturesForStore;
@@ -0,0 +1,2 @@
1
+ import { type ActionResult } from "@mohasinac/appkit/server";
2
+ export declare function enterPrizeDrawAction(input: unknown): Promise<ActionResult<unknown>>;
@@ -0,0 +1,22 @@
1
+ "use server";
2
+ import { wrapAction } from "@mohasinac/appkit/server";
3
+ import { productRepository } from "../../../../repositories";
4
+ import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
5
+ import { assertPrizeDrawOpen } from "./service";
6
+ export async function enterPrizeDrawAction(input) {
7
+ return wrapAction(async () => {
8
+ const user = await requireRoleUser(["user", "buyer", "seller", "admin"]);
9
+ const { prizeDrawId } = input;
10
+ if (!prizeDrawId)
11
+ throw new Error("prizeDrawId is required.");
12
+ const product = await productRepository.findByIdOrSlug(prizeDrawId).catch(() => null);
13
+ if (!product)
14
+ throw new Error("Prize draw not found.");
15
+ assertPrizeDrawOpen(product);
16
+ // Increment the entry count — server-side only, not exposed to the client adapter.
17
+ await productRepository.update(prizeDrawId, {
18
+ prizeCurrentEntries: (product.prizeCurrentEntries ?? 0) + 1,
19
+ });
20
+ return { entryRecorded: true, userId: user.uid };
21
+ });
22
+ }