@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
@@ -0,0 +1,42 @@
1
+ interface LotterySlotRow {
2
+ slotNumber: number;
3
+ name: string;
4
+ priceInPaise: number;
5
+ }
6
+ interface LotteryEventFormData {
7
+ title: string;
8
+ description?: string;
9
+ type: "lottery";
10
+ lotteryConfig: {
11
+ slots: Array<{
12
+ slotNumber: number;
13
+ name: string;
14
+ priceInPaise: number;
15
+ weight: number;
16
+ isBooked: boolean;
17
+ }>;
18
+ totalSlots: number;
19
+ pricingMode: "uniform" | "variable";
20
+ uniformPriceInPaise?: number;
21
+ drawWindowDurationMinutes: number;
22
+ maxPullsPerTransaction: number;
23
+ maxPullsPerUser: number;
24
+ };
25
+ }
26
+ interface LotteryAdminEditViewProps {
27
+ eventId?: string;
28
+ initialData?: {
29
+ title: string;
30
+ description?: string;
31
+ totalSlots: number;
32
+ pricingMode: "uniform" | "variable";
33
+ uniformPriceInPaise?: number;
34
+ drawWindowDurationMinutes: number;
35
+ maxPullsPerTransaction: number;
36
+ maxPullsPerUser: number;
37
+ slots: LotterySlotRow[];
38
+ };
39
+ onSubmit: (data: LotteryEventFormData) => Promise<void>;
40
+ }
41
+ export declare function LotteryAdminEditView({ eventId, initialData, onSubmit, }: LotteryAdminEditViewProps): import("react/jsx-runtime").JSX.Element;
42
+ export {};
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useTransition } from "react";
4
+ import { normalizeError } from "../../../../errors/normalize";
5
+ import { Stack, Row, Text, Heading, Section, Container, Button, DataTable, } from "../../../../ui";
6
+ import { Form, FieldInput, FieldSelect } from "../../../../ui";
7
+ export function LotteryAdminEditView({ eventId, initialData, onSubmit, }) {
8
+ const [isPending, startTransition] = useTransition();
9
+ const [error, setError] = useState(null);
10
+ const [title, setTitle] = useState(initialData?.title ?? "");
11
+ const [description, setDescription] = useState(initialData?.description ?? "");
12
+ const [pricingMode, setPricingMode] = useState(initialData?.pricingMode ?? "uniform");
13
+ const [uniformPrice, setUniformPrice] = useState(String((initialData?.uniformPriceInPaise ?? 0) / 100));
14
+ const [drawWindowMinutes, setDrawWindowMinutes] = useState(String(initialData?.drawWindowDurationMinutes ?? 5));
15
+ const [maxPullsPerTx, setMaxPullsPerTx] = useState(String(initialData?.maxPullsPerTransaction ?? 1));
16
+ const [maxPullsPerUser, setMaxPullsPerUser] = useState(String(initialData?.maxPullsPerUser ?? 1));
17
+ const [slots, setSlots] = useState(initialData?.slots ?? [{ slotNumber: 1, name: "", priceInPaise: 0 }]);
18
+ const addSlot = () => {
19
+ setSlots((prev) => [
20
+ ...prev,
21
+ { slotNumber: prev.length + 1, name: "", priceInPaise: 0 },
22
+ ]);
23
+ };
24
+ const removeSlot = (idx) => {
25
+ setSlots((prev) => prev.filter((_, i) => i !== idx).map((s, i) => ({ ...s, slotNumber: i + 1 })));
26
+ };
27
+ const updateSlot = (idx, field, value) => {
28
+ setSlots((prev) => prev.map((s, i) => i === idx
29
+ ? { ...s, [field]: field === "priceInPaise" ? Math.round(parseFloat(value) * 100) || 0 : value }
30
+ : s));
31
+ };
32
+ const handleSubmit = () => {
33
+ setError(null);
34
+ startTransition(async () => {
35
+ try {
36
+ const lotteryConfig = {
37
+ slots: slots.map((s) => ({
38
+ slotNumber: s.slotNumber,
39
+ name: s.name,
40
+ priceInPaise: s.priceInPaise,
41
+ weight: 0,
42
+ isBooked: false,
43
+ })),
44
+ totalSlots: slots.length,
45
+ pricingMode,
46
+ uniformPriceInPaise: pricingMode === "uniform" ? Math.round(parseFloat(uniformPrice) * 100) || 0 : undefined,
47
+ drawWindowDurationMinutes: parseInt(drawWindowMinutes, 10) || 5,
48
+ maxPullsPerTransaction: parseInt(maxPullsPerTx, 10) || 1,
49
+ maxPullsPerUser: parseInt(maxPullsPerUser, 10) || 1,
50
+ };
51
+ await onSubmit({ title, description, type: "lottery", lotteryConfig });
52
+ }
53
+ catch (err) {
54
+ void normalizeError(err);
55
+ setError(err instanceof Error ? err.message : "Failed to save lottery");
56
+ }
57
+ });
58
+ };
59
+ // Slot table columns
60
+ const slotColumns = [
61
+ {
62
+ key: "slotNumber",
63
+ header: "#",
64
+ render: (s) => _jsx(Text, { size: "xs", color: "muted", family: "mono", children: s.slotNumber }),
65
+ },
66
+ {
67
+ key: "name",
68
+ header: "Prize Name",
69
+ render: (s) => (_jsx("input", { type: "text", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-2 py-1 text-sm", placeholder: `Prize for slot ${s.slotNumber}`, value: s.name, onChange: (e) => updateSlot(s._idx, "name", e.target.value), "aria-label": `Slot ${s.slotNumber} prize name` })),
70
+ },
71
+ ...(pricingMode === "variable"
72
+ ? [
73
+ {
74
+ key: "priceInPaise",
75
+ header: "Price (₹)",
76
+ render: (s) => (_jsx("input", { type: "number", className: "w-24 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-2 py-1 text-sm", placeholder: "0", value: s.priceInPaise / 100, onChange: (e) => updateSlot(s._idx, "priceInPaise", e.target.value), "aria-label": `Slot ${s.slotNumber} price` })),
77
+ },
78
+ ]
79
+ : []),
80
+ ];
81
+ const slotsWithIdx = slots.map((s, i) => ({ ...s, _idx: i }));
82
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-6", children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "xl", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "bold", children: eventId ? "Edit Lottery" : "Create Lottery" }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Basic Info" }), _jsx(FieldInput, { name: "title", label: "Title", required: true, value: title, onChange: (v) => { setTitle(v); clearErrors(); } }), _jsx(FieldInput, { name: "description", label: "Description", value: description, onChange: (v) => { setDescription(v); clearErrors(); } })] }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "lg", weight: "semibold", children: "Configuration" }), _jsx(FieldSelect, { name: "pricingMode", label: "Pricing Mode", value: pricingMode, options: [
83
+ { label: "Uniform (all slots same price)", value: "uniform" },
84
+ { label: "Variable (per-slot pricing)", value: "variable" },
85
+ ], onChange: (v) => setPricingMode(v) }), pricingMode === "uniform" && (_jsx(FieldInput, { name: "uniformPrice", label: "Price per Slot (\u20B9)", type: "number", value: uniformPrice, onChange: (v) => setUniformPrice(v) })), _jsx(FieldInput, { name: "drawWindowMinutes", label: "Draw Window (minutes)", type: "number", value: drawWindowMinutes, onChange: (v) => setDrawWindowMinutes(v) }), _jsx(FieldInput, { name: "maxPullsPerTx", label: "Max Pulls per Transaction", type: "number", value: maxPullsPerTx, onChange: (v) => setMaxPullsPerTx(v) }), _jsx(FieldInput, { name: "maxPullsPerUser", label: "Max Pulls per User", type: "number", value: maxPullsPerUser, onChange: (v) => setMaxPullsPerUser(v) })] }), _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { align: "center", justify: "between", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "semibold", children: ["Slots (", slots.length, ")"] }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: addSlot, disabled: slots.length >= 200, children: "+ Add Slot" })] }), _jsx(DataTable, { data: slotsWithIdx, columns: slotColumns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots yet.", actions: (s) => slots.length > 1 ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeSlot(s._idx), "aria-label": `Remove slot ${s.slotNumber}`, children: "\u00D7" })) : null })] }), error && _jsx(Text, { className: "text-error", size: "sm", role: "alert", children: error }), _jsx(Button, { type: "submit", variant: "primary", isLoading: isPending, onClick: handleSubmit, className: "w-full sm:w-auto", children: isPending ? "Saving…" : eventId ? "Update Lottery" : "Create Lottery" })] })) }) }) }));
86
+ }
@@ -0,0 +1,14 @@
1
+ import type { ClientLotterySlot } from "../../../../features/lottery/types";
2
+ interface AdminLotterySlot extends ClientLotterySlot {
3
+ priceInPaise: number;
4
+ weight: number;
5
+ }
6
+ interface LotteryAdminSlotViewProps {
7
+ slots: AdminLotterySlot[];
8
+ }
9
+ /**
10
+ * Admin-only view showing slots with price + weight + % chance.
11
+ * Separate from LotterySlotGrid (public) which never shows price/weight.
12
+ */
13
+ export declare function LotteryAdminSlotView({ slots }: LotteryAdminSlotViewProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { Stack, Text, Heading, Badge, Section, Container, DataTable, } from "../../../../ui";
4
+ /**
5
+ * Admin-only view showing slots with price + weight + % chance.
6
+ * Separate from LotterySlotGrid (public) which never shows price/weight.
7
+ */
8
+ export function LotteryAdminSlotView({ slots }) {
9
+ const totalWeight = slots.reduce((s, sl) => s + sl.weight, 0);
10
+ const columns = [
11
+ {
12
+ key: "slotNumber",
13
+ header: "Slot #",
14
+ render: (s) => _jsxs(Text, { size: "sm", weight: "semibold", family: "mono", children: ["#", s.slotNumber] }),
15
+ },
16
+ {
17
+ key: "name",
18
+ header: "Name",
19
+ render: (s) => _jsx(Text, { size: "sm", children: s.name }),
20
+ },
21
+ {
22
+ key: "priceInPaise",
23
+ header: "Price (₹)",
24
+ render: (s) => (_jsxs(Text, { size: "sm", family: "mono", children: ["\u20B9", (s.priceInPaise / 100).toLocaleString("en-IN")] })),
25
+ },
26
+ {
27
+ key: "weight",
28
+ header: "Weight",
29
+ render: (s) => _jsx(Text, { size: "sm", family: "mono", children: s.weight }),
30
+ },
31
+ {
32
+ key: "status",
33
+ header: "% Chance",
34
+ render: (s) => {
35
+ const chance = totalWeight > 0 ? ((s.weight / totalWeight) * 100).toFixed(1) : "0.0";
36
+ return _jsxs(Text, { size: "sm", family: "mono", children: [chance, "%"] });
37
+ },
38
+ },
39
+ {
40
+ key: "isBooked",
41
+ header: "Status",
42
+ render: (s) => (_jsx(Badge, { variant: s.isBooked ? "success" : "secondary", size: "sm", children: s.isBooked ? "Claimed" : "Available" })),
43
+ },
44
+ ];
45
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "xl", weight: "bold", children: "Slot Analysis (Admin Only)" }), _jsx(Text, { size: "sm", color: "muted", children: "Price and weight data is never exposed to store owners or users." }), _jsx(DataTable, { data: slots, columns: columns, keyExtractor: (s) => String(s.slotNumber), emptyMessage: "No slots defined." })] }) }) }));
46
+ }
@@ -0,0 +1,28 @@
1
+ import type { ClientLotteryConfig } from "../../../../features/lottery/types";
2
+ interface ClientLotteryEvent {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ status: string;
7
+ endsAt?: string | Date | null;
8
+ coverImageUrl?: string;
9
+ lotteryConfig?: ClientLotteryConfig;
10
+ }
11
+ interface LotteryDetailViewProps {
12
+ event: ClientLotteryEvent;
13
+ user?: {
14
+ uid: string;
15
+ displayName?: string | null;
16
+ } | null;
17
+ currentEntry?: {
18
+ userLotteryNumber: number;
19
+ assignedPrizeSlotNumber?: number;
20
+ slotName?: string;
21
+ } | null;
22
+ }
23
+ /**
24
+ * Full lottery detail page view.
25
+ * Shows cover + description + slot grid + pull form (if active + logged in).
26
+ */
27
+ export declare function LotteryDetailView({ event, user, currentEntry }: LotteryDetailViewProps): import("react/jsx-runtime").JSX.Element;
28
+ export {};
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Stack, Row, Text, Heading, Badge, Section, Container, Div, Anchor, } from "../../../../ui";
5
+ import { LotterySlotGrid } from "./LotterySlotGrid";
6
+ import { LotteryPullForm } from "./LotteryPullForm";
7
+ /**
8
+ * Full lottery detail page view.
9
+ * Shows cover + description + slot grid + pull form (if active + logged in).
10
+ */
11
+ export function LotteryDetailView({ event, user, currentEntry }) {
12
+ const [pulledEntry, setPulledEntry] = useState(currentEntry?.assignedPrizeSlotNumber != null ? currentEntry : null);
13
+ const config = event.lotteryConfig;
14
+ const isActive = event.status === "active";
15
+ const isEnded = event.status === "ended" || event.status === "cancelled";
16
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [event.coverImageUrl ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: event.coverImageUrl, alt: event.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "subtle", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDFB0" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: isActive ? "success" : isEnded ? "danger" : "warning", children: event.status }), config && (_jsxs(Badge, { variant: "info", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " slots claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: event.title }), event.description ? (_jsx(Text, { color: "muted", size: "sm", children: event.description.replace(/<[^>]+>/g, "").slice(0, 200) })) : null, event.endsAt ? (_jsxs(Text, { size: "sm", color: "muted", children: ["Ends: ", new Date(event.endsAt).toLocaleDateString("en-IN", { dateStyle: "long" })] })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Participate?" }), _jsx(Text, { color: "muted", children: "Log in to submit your lottery entry." }), _jsx(Anchor, { href: "/login", tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Lottery #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "event", eventId: event.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) })), isEnded && !pulledEntry && (_jsx(Stack, { gap: "sm", surface: "muted", padding: "md", rounded: "xl", children: _jsx(Text, { color: "muted", weight: "semibold", children: "This lottery has ended." }) }))] }) }) }));
17
+ }
@@ -0,0 +1,23 @@
1
+ interface LotteryEntryRow {
2
+ id: string;
3
+ userLotteryNumber: number;
4
+ userDisplayName?: string;
5
+ userId: string;
6
+ transactionId?: string;
7
+ userPhone?: string;
8
+ assignedPrizeSlotNumber?: number;
9
+ status: string;
10
+ isFlagged: boolean;
11
+ submittedAt?: string | Date;
12
+ }
13
+ interface LotteryEntriesViewProps {
14
+ sourceType: "event" | "product";
15
+ sourceId: string;
16
+ entries: LotteryEntryRow[];
17
+ isAdmin: boolean;
18
+ isStoreOwner?: boolean;
19
+ onFlagEntry?: (entryId: string, flagNote: string) => Promise<void>;
20
+ onReopenSlot?: (slotNumber: number) => Promise<void>;
21
+ }
22
+ export declare function LotteryEntriesView({ entries, isAdmin, isStoreOwner, onFlagEntry, onReopenSlot, }: LotteryEntriesViewProps): import("react/jsx-runtime").JSX.Element;
23
+ export {};
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Stack, Row, Text, Heading, Badge, Button, Section, Container, DataTable, } from "../../../../ui";
5
+ import { Dialog } from "../../../../ui/components/Dialog";
6
+ import { FieldTextarea } from "../../../../ui/forms/FieldTextarea";
7
+ export function LotteryEntriesView({ entries, isAdmin, isStoreOwner = false, onFlagEntry, onReopenSlot, }) {
8
+ const [flaggingId, setFlaggingId] = useState(null);
9
+ const [flagNote, setFlagNote] = useState("");
10
+ const canViewSensitive = isAdmin || isStoreOwner;
11
+ const columns = [
12
+ {
13
+ key: "userLotteryNumber",
14
+ header: "#",
15
+ render: (e) => _jsxs(Text, { size: "sm", weight: "semibold", family: "mono", children: ["#", e.userLotteryNumber] }),
16
+ },
17
+ {
18
+ key: "userDisplayName",
19
+ header: "Participant",
20
+ render: (e) => _jsx(Text, { size: "sm", children: e.userDisplayName ?? e.userId }),
21
+ },
22
+ ...(canViewSensitive
23
+ ? [
24
+ {
25
+ key: "transactionId",
26
+ header: "TX ID",
27
+ render: (e) => _jsx(Text, { size: "xs", color: "muted", family: "mono", children: e.transactionId ?? "—" }),
28
+ },
29
+ {
30
+ key: "userPhone",
31
+ header: "Phone",
32
+ render: (e) => _jsx(Text, { size: "xs", color: "muted", family: "mono", children: e.userPhone ?? "—" }),
33
+ },
34
+ ]
35
+ : []),
36
+ {
37
+ key: "assignedPrizeSlotNumber",
38
+ header: "Slot",
39
+ render: (e) => e.assignedPrizeSlotNumber != null ? (_jsxs(Badge, { variant: "info", size: "sm", children: ["Slot #", e.assignedPrizeSlotNumber] })) : (_jsx(Text, { size: "sm", children: "\u2014" })),
40
+ },
41
+ {
42
+ key: "status",
43
+ header: "Status",
44
+ render: (e) => (_jsx(Badge, { variant: e.status === "drawn" || e.status === "won" ? "success"
45
+ : e.status === "flagged" ? "danger"
46
+ : e.status === "cancelled" ? "secondary"
47
+ : "warning", size: "sm", children: e.status })),
48
+ },
49
+ ];
50
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "lg", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "bold", children: "Lottery Entries" }), _jsxs(Text, { color: "muted", children: [entries.length, " ", entries.length === 1 ? "entry" : "entries", " total"] }), _jsx(DataTable, { data: entries, columns: columns, keyExtractor: (e) => e.id, emptyMessage: "No entries yet.", actions: isAdmin
51
+ ? (entry) => (_jsxs(Row, { gap: "xs", children: [!entry.isFlagged && onFlagEntry && (_jsx(Button, { variant: "danger", size: "sm", onClick: () => { setFlaggingId(entry.id); setFlagNote(""); }, children: "Flag" })), entry.isFlagged && entry.assignedPrizeSlotNumber != null && onReopenSlot && (_jsx(Button, { variant: "secondary", size: "sm", onClick: () => onReopenSlot(entry.assignedPrizeSlotNumber), children: "Reopen Slot" }))] }))
52
+ : undefined }), _jsx(Dialog, { open: !!flaggingId, onClose: () => setFlaggingId(null), padding: "lg", "aria-label": "Flag entry", children: _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "xl", weight: "bold", children: "Flag This Entry?" }), _jsx(Text, { color: "muted", size: "sm", children: "Entry will be marked as fraudulent. Their claimed slot stays booked until you manually reopen it." }), _jsx(FieldTextarea, { name: "flagNote", label: "Reason for flagging", required: true, value: flagNote, onChange: (v) => setFlagNote(v), rows: 3 }), _jsxs(Row, { gap: "sm", justify: "end", children: [_jsx(Button, { variant: "ghost", onClick: () => setFlaggingId(null), children: "Cancel" }), _jsx(Button, { variant: "danger", disabled: !flagNote.trim(), onClick: async () => {
53
+ if (onFlagEntry && flaggingId && flagNote.trim()) {
54
+ await onFlagEntry(flaggingId, flagNote.trim());
55
+ setFlaggingId(null);
56
+ }
57
+ }, children: "Flag Entry" })] })] }) })] }) }) }));
58
+ }
@@ -0,0 +1,21 @@
1
+ import type { ClientLotteryConfig } from "../../../../features/lottery/types";
2
+ interface ClientLotteryEvent {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ status: string;
7
+ startsAt?: string | Date;
8
+ endsAt?: string | Date;
9
+ coverImageUrl?: string;
10
+ lotteryConfig?: ClientLotteryConfig;
11
+ }
12
+ interface LotteryListViewProps {
13
+ items: ClientLotteryEvent[];
14
+ adminMode?: boolean;
15
+ }
16
+ /**
17
+ * Card grid of lotteries.
18
+ * Admin sees all statuses; public sees active only.
19
+ */
20
+ export declare function LotteryListView({ items, adminMode }: LotteryListViewProps): import("react/jsx-runtime").JSX.Element;
21
+ export {};
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Stack, Row, Text, Heading, Badge, Card, Section, Container, Anchor, Div, Grid, } from "../../../../ui";
4
+ /**
5
+ * Card grid of lotteries.
6
+ * Admin sees all statuses; public sees active only.
7
+ */
8
+ export function LotteryListView({ items, adminMode = false }) {
9
+ const visible = adminMode
10
+ ? items
11
+ : items.filter((e) => e.status === "active");
12
+ if (visible.length === 0) {
13
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { className: "text-center", gap: "md", padding: "xl", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "bold", children: "No Active Lotteries" }), _jsx(Text, { color: "muted", children: "Check back soon for upcoming lottery events!" })] }) }) }));
14
+ }
15
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "lg", children: [_jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: adminMode ? "All Lotteries" : "Active Lotteries" }), _jsx(Grid, { cols: 3, gap: "md", children: visible.map((event) => {
16
+ const claimed = event.lotteryConfig?.slots.filter((s) => s.isBooked).length ?? 0;
17
+ const total = event.lotteryConfig?.totalSlots ?? 0;
18
+ const slotsLeft = total - claimed;
19
+ return (_jsx(Anchor, { href: `/lottery/${event.id}`, tone: "brand", rounded: "2xl", className: "block focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", "aria-label": `${event.title} lottery`, children: _jsxs(Card, { variant: "default", padding: "none", animate: "hoverLift", className: "overflow-hidden", children: [event.coverImageUrl ? (_jsx(Div, { className: "aspect-video overflow-hidden", children: _jsx("img", { src: event.coverImageUrl, alt: event.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { className: "aspect-video", surface: "muted", align: "center", justify: "center", children: _jsx(Text, { size: "3xl", children: "\uD83C\uDFB0" }) })), _jsxs(Stack, { gap: "xs", padding: "md", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: event.status === "active"
20
+ ? "success"
21
+ : event.status === "ended"
22
+ ? "danger"
23
+ : "warning", size: "sm", children: event.status }), slotsLeft > 0 && event.status === "active" && (_jsxs(Badge, { variant: "info", size: "sm", children: [slotsLeft, " slot", slotsLeft !== 1 ? "s" : "", " left"] })), slotsLeft === 0 && total > 0 && (_jsx(Badge, { variant: "secondary", size: "sm", children: "Full" }))] }), _jsx(Heading, { level: 3, size: "lg", weight: "semibold", className: "truncate", children: event.title }), event.description ? (_jsx(Text, { size: "sm", color: "muted", className: "truncate", children: event.description.replace(/<[^>]+>/g, "").slice(0, 100) })) : null, total > 0 && (_jsxs(Text, { size: "xs", color: "muted", children: [claimed, "/", total, " slots claimed"] }))] })] }) }, event.id));
24
+ }) })] }) }) }));
25
+ }
@@ -0,0 +1,19 @@
1
+ interface LotteryPullFormProps {
2
+ sourceType: "event" | "product";
3
+ eventId?: string;
4
+ productId?: string;
5
+ totalSlots: number;
6
+ maxPullsPerUser: number;
7
+ onSuccess?: (result: {
8
+ userLotteryNumber: number;
9
+ assignedPrizeSlotNumber: number;
10
+ slotName: string;
11
+ }) => void;
12
+ }
13
+ /**
14
+ * User-facing lottery pull form.
15
+ * Submits TX ID + phone + payment time + item number.
16
+ * On success, shows the user their lottery number and assigned prize slot.
17
+ */
18
+ export declare function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser: _maxPullsPerUser, onSuccess, }: LotteryPullFormProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Stack, Row, Text, Heading, Span, } from "../../../../ui";
5
+ import { Form, FieldInput, Button } from "../../../../ui";
6
+ import { useApiMutation } from "../../../../client/api/useApiMutation";
7
+ import { apiClient } from "../../../../http";
8
+ /**
9
+ * User-facing lottery pull form.
10
+ * Submits TX ID + phone + payment time + item number.
11
+ * On success, shows the user their lottery number and assigned prize slot.
12
+ */
13
+ export function LotteryPullForm({ sourceType, eventId, productId, totalSlots, maxPullsPerUser: _maxPullsPerUser, onSuccess, }) {
14
+ const [result, setResult] = useState(null);
15
+ const [transactionId, setTransactionId] = useState("");
16
+ const [paymentTime, setPaymentTime] = useState("");
17
+ const [itemNumber, setItemNumber] = useState("");
18
+ const [userPhone, setUserPhone] = useState("");
19
+ const apiRoute = sourceType === "event"
20
+ ? `/api/events/${eventId ?? ""}/lottery-pull`
21
+ : `/api/products/${productId ?? ""}/lottery-pull`;
22
+ const mutation = useApiMutation({
23
+ mutationFn: () => apiClient.post(apiRoute, {
24
+ sourceType,
25
+ ...(sourceType === "event" ? { eventId } : { productId }),
26
+ transactionId,
27
+ paymentTime: new Date(paymentTime).toISOString(),
28
+ purchasedItemNumber: parseInt(itemNumber, 10),
29
+ userPhone,
30
+ }),
31
+ successMessage: "Your lottery entry has been submitted!",
32
+ onSuccess: (data) => {
33
+ if (data.data) {
34
+ setResult(data.data);
35
+ onSuccess?.(data.data);
36
+ }
37
+ },
38
+ });
39
+ if (result) {
40
+ return (_jsxs(Stack, { gap: "sm", padding: "md", rounded: "2xl", surface: "success-surface", className: "border border-success/20", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { layout: "inline-flex", color: "inverse", weight: "semibold", className: "bg-success text-[11px] tracking-wide", padding: "pill-sm", rounded: "full", transform: "uppercase", children: "Entry Confirmed" }), _jsxs(Heading, { level: 2, className: "text-success", size: "lg", weight: "bold", children: ["You're #", result.userLotteryNumber, "!"] })] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["You've been assigned", " ", _jsxs(Span, { weight: "bold", children: ["Slot #", result.assignedPrizeSlotNumber] }), result.slotName ? ` — ${result.slotName}` : "", ". Good luck!"] })] }));
41
+ }
42
+ return (_jsx(Form, { onSubmit: (e) => e.preventDefault(), className: "space-y-4", children: ({ setFieldError, clearErrors }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, size: "lg", weight: "semibold", children: "Submit Your Entry" }), _jsx(Text, { size: "sm", color: "muted", children: "Enter your UPI Transaction ID and payment details to claim your slot." }), _jsx(FieldInput, { name: "transactionId", label: "Transaction ID (UPI Ref / Payment Ref)", placeholder: "e.g. 123456789012", required: true, value: transactionId, onChange: (v) => { setTransactionId(v); clearErrors(); } }), _jsx(FieldInput, { name: "paymentTime", label: "Payment Date & Time", type: "datetime-local", required: true, value: paymentTime, onChange: (v) => { setPaymentTime(v); clearErrors(); } }), _jsx(FieldInput, { name: "itemNumber", label: `Slot Number (1 – ${totalSlots})`, type: "number", placeholder: `Enter a number between 1 and ${totalSlots}`, required: true, value: itemNumber, onChange: (v) => { setItemNumber(v); clearErrors(); } }), _jsx(FieldInput, { name: "userPhone", label: "Your Phone Number", type: "tel", placeholder: "e.g. 9876543210", required: true, value: userPhone, onChange: (v) => { setUserPhone(v); clearErrors(); } }), _jsx(Button, { type: "submit", variant: "primary", isLoading: mutation.isPending, onClick: () => {
43
+ clearErrors();
44
+ const num = parseInt(itemNumber, 10);
45
+ let valid = true;
46
+ if (!transactionId || transactionId.length < 4) {
47
+ setFieldError("transactionId", "Transaction ID must be at least 4 characters");
48
+ valid = false;
49
+ }
50
+ if (!paymentTime) {
51
+ setFieldError("paymentTime", "Payment date & time is required");
52
+ valid = false;
53
+ }
54
+ if (isNaN(num) || num < 1 || num > totalSlots) {
55
+ setFieldError("itemNumber", `Slot number must be between 1 and ${totalSlots}`);
56
+ valid = false;
57
+ }
58
+ if (!userPhone || userPhone.replace(/\D/g, "").length < 10) {
59
+ setFieldError("userPhone", "Enter a valid phone number (minimum 10 digits)");
60
+ valid = false;
61
+ }
62
+ if (valid)
63
+ mutation.mutate();
64
+ }, className: "w-full", children: mutation.isPending ? "Submitting…" : "Submit Entry" })] })) }));
65
+ }
@@ -0,0 +1,13 @@
1
+ import type { ClientLotterySlot } from "../../../../features/lottery/types";
2
+ interface LotterySlotGridProps {
3
+ slots: ClientLotterySlot[];
4
+ totalSlots: number;
5
+ }
6
+ /**
7
+ * Visual grid of lottery slots.
8
+ * Booked slots show buyer display name + user lottery number in green.
9
+ * Available slots show slot number + name in white.
10
+ * Never shows price or weight.
11
+ */
12
+ export declare function LotterySlotGrid({ slots, totalSlots }: LotterySlotGridProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Stack, Row, Text, Span, Div } from "../../../../ui";
4
+ /**
5
+ * Visual grid of lottery slots.
6
+ * Booked slots show buyer display name + user lottery number in green.
7
+ * Available slots show slot number + name in white.
8
+ * Never shows price or weight.
9
+ */
10
+ export function LotterySlotGrid({ slots, totalSlots }) {
11
+ const cols = totalSlots <= 10 ? 5 : totalSlots <= 25 ? 5 : totalSlots <= 50 ? 10 : totalSlots <= 100 ? 10 : 20;
12
+ return (_jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "sm", align: "center", children: [_jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Span, { layout: "inline-block", className: "w-3 h-3", rounded: "sm", surface: "success-surface" }), _jsx(Text, { size: "xs", color: "muted", children: "Claimed" })] }), _jsxs(Row, { gap: "xs", align: "center", children: [_jsx(Span, { layout: "inline-block", className: "w-3 h-3 border border-[var(--appkit-color-border)]", rounded: "sm", surface: "muted" }), _jsx(Text, { size: "xs", color: "muted", children: "Available" })] })] }), _jsxs(Div, { style: { display: "grid", gap: "4px", gridTemplateColumns: `repeat(${Math.min(cols, totalSlots)}, minmax(0, 1fr))` }, "aria-label": "Lottery slot grid", children: [slots.map((slot) => (_jsx(Div, { title: slot.isBooked
13
+ ? `Slot #${slot.slotNumber}: ${slot.name} — claimed by ${slot.bookedByDisplayName ?? "a participant"} (#${slot.bookedByUserLotteryNumber ?? "?"})`
14
+ : `Slot #${slot.slotNumber}: ${slot.name} — available`, "aria-label": `Slot ${slot.slotNumber}: ${slot.isBooked ? "claimed" : "available"}`, className: [
15
+ "aspect-square rounded-sm flex items-center justify-center text-[10px] font-mono font-semibold transition-colors",
16
+ slot.isBooked
17
+ ? "text-success border border-success/30"
18
+ : "text-zinc-400 border border-[var(--appkit-color-border-subtle)] hover:border-primary/40",
19
+ ].join(" "), surface: slot.isBooked ? "success-surface" : "subtle", children: slot.slotNumber }, slot.slotNumber))), slots.length < totalSlots &&
20
+ Array.from({ length: totalSlots - slots.length }, (_, i) => (_jsx(Div, { rounded: "sm", surface: "subtle", className: "aspect-square border border-[var(--appkit-color-border-subtle)]", "aria-hidden": "true" }, `empty-${i}`)))] }), _jsxs(Text, { size: "xs", color: "muted", children: [slots.filter((s) => s.isBooked).length, " / ", totalSlots, " slots claimed"] })] }));
21
+ }
@@ -0,0 +1,28 @@
1
+ import type { ClientLotteryConfig } from "../../../../features/lottery/types";
2
+ interface ClientProduct {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ status: string;
7
+ mainImage?: string;
8
+ prizeDrawMode?: "reveal" | "lottery";
9
+ lotteryConfig?: ClientLotteryConfig;
10
+ }
11
+ interface PrizeDrawLotteryDetailViewProps {
12
+ product: ClientProduct;
13
+ user?: {
14
+ uid: string;
15
+ displayName?: string | null;
16
+ } | null;
17
+ currentEntry?: {
18
+ userLotteryNumber: number;
19
+ assignedPrizeSlotNumber?: number;
20
+ slotName?: string;
21
+ } | null;
22
+ }
23
+ /**
24
+ * Prize-draw product detail view for lottery mode.
25
+ * Same flow as LotteryDetailView but sourced from a product.
26
+ */
27
+ export declare function PrizeDrawLotteryDetailView({ product, user, currentEntry, }: PrizeDrawLotteryDetailViewProps): import("react/jsx-runtime").JSX.Element;
28
+ export {};
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Stack, Row, Text, Heading, Badge, Section, Container, Div, Anchor, } from "../../../../ui";
5
+ import { LotterySlotGrid } from "./LotterySlotGrid";
6
+ import { LotteryPullForm } from "./LotteryPullForm";
7
+ /**
8
+ * Prize-draw product detail view for lottery mode.
9
+ * Same flow as LotteryDetailView but sourced from a product.
10
+ */
11
+ export function PrizeDrawLotteryDetailView({ product, user, currentEntry, }) {
12
+ const [pulledEntry, setPulledEntry] = useState(currentEntry?.assignedPrizeSlotNumber != null
13
+ ? currentEntry
14
+ : null);
15
+ const config = product.lotteryConfig;
16
+ const isActive = product.status === "published";
17
+ return (_jsx(Container, { children: _jsx(Section, { children: _jsxs(Stack, { gap: "xl", children: [product.mainImage ? (_jsx(Div, { rounded: "2xl", className: "overflow-hidden", style: { aspectRatio: "16/9", maxHeight: "16rem" }, children: _jsx("img", { src: product.mainImage, alt: product.title, className: "w-full h-full object-cover" }) })) : (_jsx(Div, { rounded: "2xl", surface: "muted", padding: "xl", align: "center", justify: "center", children: _jsx(Text, { size: "5xl", children: "\uD83C\uDF81" }) })), _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, children: [_jsx(Badge, { variant: "info", children: "Lottery Prize Draw" }), config && (_jsxs(Badge, { variant: isActive ? "success" : "secondary", children: [config.slots.filter((s) => s.isBooked).length, "/", config.totalSlots, " claimed"] }))] }), _jsx(Heading, { level: 1, size: "3xl", weight: "bold", children: product.title }), product.description ? (_jsx(Text, { color: "muted", children: product.description })) : null] }), config && config.slots.length > 0 ? (_jsxs(Stack, { gap: "sm", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Slots" }), _jsx(LotterySlotGrid, { slots: config.slots, totalSlots: config.totalSlots })] })) : null, isActive && config && (_jsx(Div, { padding: "md", rounded: "2xl", surface: "card", className: "border border-[var(--appkit-color-border)]", children: !user ? (_jsxs(Stack, { gap: "md", className: "text-center", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", children: "Want to Enter?" }), _jsx(Text, { color: "muted", children: "Log in to submit your entry." }), _jsx(Anchor, { href: "/login", tone: "brand", children: "Log In to Enter" })] })) : pulledEntry ? (_jsxs(Stack, { gap: "sm", surface: "success-surface", padding: "md", rounded: "xl", className: "border border-success/20", children: [_jsxs(Heading, { level: 2, size: "lg", weight: "bold", className: "text-success", children: ["You're Entry #", pulledEntry.userLotteryNumber, "!"] }), _jsxs(Text, { className: "text-success", size: "sm", children: ["Assigned to Slot #", pulledEntry.assignedPrizeSlotNumber, pulledEntry.slotName ? ` — ${pulledEntry.slotName}` : "", "."] })] })) : (_jsx(LotteryPullForm, { sourceType: "product", productId: product.id, totalSlots: config.totalSlots, maxPullsPerUser: config.maxPullsPerUser, onSuccess: (res) => setPulledEntry(res) })) }))] }) }) }));
18
+ }