@mohasinac/appkit 3.0.6 → 3.1.1

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 (186) 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/checkout/__tests__/actions.test.d.ts +1 -0
  20. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +600 -0
  21. package/dist/_internal/server/features/lottery/actions.d.ts +43 -0
  22. package/dist/_internal/server/features/lottery/actions.js +243 -0
  23. package/dist/_internal/server/features/lottery/adapters.d.ts +9 -0
  24. package/dist/_internal/server/features/lottery/adapters.js +21 -0
  25. package/dist/_internal/server/features/lottery/data.d.ts +20 -0
  26. package/dist/_internal/server/features/lottery/data.js +41 -0
  27. package/dist/_internal/server/features/lottery/metadata.d.ts +6 -0
  28. package/dist/_internal/server/features/lottery/metadata.js +31 -0
  29. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +1 -0
  30. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +263 -0
  31. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +1 -0
  32. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +249 -0
  33. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +1 -0
  34. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +201 -0
  35. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +1 -0
  36. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +169 -0
  37. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +1 -0
  38. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +148 -0
  39. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +1 -0
  40. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +210 -0
  41. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +1 -0
  42. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +190 -0
  43. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +1 -0
  44. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +161 -0
  45. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +1 -0
  46. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +302 -0
  47. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +1 -0
  48. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +252 -0
  49. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +1 -0
  50. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +129 -0
  51. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  52. package/dist/_internal/shared/actions/action-registry.js +46 -0
  53. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  54. package/dist/client.d.ts +9 -0
  55. package/dist/client.js +9 -0
  56. package/dist/constants/field-names.d.ts +5 -1
  57. package/dist/constants/field-names.js +5 -1
  58. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +1 -0
  59. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +386 -0
  60. package/dist/features/admin/api/bids/route.d.ts +2 -2
  61. package/dist/features/admin/api/coupons/route.d.ts +2 -2
  62. package/dist/features/admin/api/products/route.d.ts +2 -2
  63. package/dist/features/admin/api/reviews/route.d.ts +2 -2
  64. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +1 -0
  65. package/dist/features/admin/repository/__tests__/notification.repository.test.js +356 -0
  66. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +1 -0
  67. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +298 -0
  68. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +1 -0
  69. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +290 -0
  70. package/dist/features/auth/api/route.d.ts +2 -2
  71. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +1 -0
  72. package/dist/features/auth/repository/__tests__/session.repository.test.js +310 -0
  73. package/dist/features/auth/repository/__tests__/session.test.d.ts +1 -0
  74. package/dist/features/auth/repository/__tests__/session.test.js +146 -0
  75. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +1 -0
  76. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +171 -0
  77. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +1 -0
  78. package/dist/features/auth/repository/__tests__/sms-counter.test.js +88 -0
  79. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +1 -0
  80. package/dist/features/auth/repository/__tests__/token.repository.test.js +260 -0
  81. package/dist/features/auth/repository/__tests__/token.test.d.ts +1 -0
  82. package/dist/features/auth/repository/__tests__/token.test.js +140 -0
  83. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +1 -0
  84. package/dist/features/auth/repository/__tests__/user.repository.test.js +352 -0
  85. package/dist/features/auth/repository/__tests__/user.test.d.ts +1 -0
  86. package/dist/features/auth/repository/__tests__/user.test.js +226 -0
  87. package/dist/features/auth/repository/session.repository.js +10 -1
  88. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +1 -0
  89. package/dist/features/cart/repository/__tests__/cart.repository.test.js +371 -0
  90. package/dist/features/cart/repository/cart.repository.js +2 -2
  91. package/dist/features/categories/api/[id]/route.d.ts +4 -4
  92. package/dist/features/categories/api/route.d.ts +2 -2
  93. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +1 -0
  94. package/dist/features/categories/repository/__tests__/categories.repository.test.js +813 -0
  95. package/dist/features/events/components/EventCard.js +1 -0
  96. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +1 -0
  97. package/dist/features/events/repository/__tests__/event.repository.test.js +299 -0
  98. package/dist/features/events/schemas/firestore.d.ts +3 -0
  99. package/dist/features/events/schemas/index.d.ts +834 -14
  100. package/dist/features/events/schemas/index.js +80 -1
  101. package/dist/features/events/types/index.d.ts +4 -1
  102. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +1 -0
  103. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +311 -0
  104. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +1 -0
  105. package/dist/features/history/repository/__tests__/user-history.repository.test.js +180 -0
  106. package/dist/features/homepage/api/[id]/route.d.ts +4 -4
  107. package/dist/features/homepage/api/carousel/[id]/route.d.ts +4 -4
  108. package/dist/features/homepage/api/carousel/route.d.ts +2 -2
  109. package/dist/features/homepage/api/route.d.ts +2 -2
  110. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +1 -0
  111. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +182 -0
  112. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +1 -0
  113. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +185 -0
  114. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +33 -0
  115. package/dist/features/lottery/repository/lottery-entry.repository.js +130 -0
  116. package/dist/features/lottery/schemas/firestore.d.ts +49 -0
  117. package/dist/features/lottery/schemas/firestore.js +25 -0
  118. package/dist/features/lottery/schemas/zod.d.ts +113 -0
  119. package/dist/features/lottery/schemas/zod.js +39 -0
  120. package/dist/features/lottery/types/index.d.ts +67 -0
  121. package/dist/features/lottery/types/index.js +55 -0
  122. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +1 -0
  123. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +257 -0
  124. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +1 -0
  125. package/dist/features/orders/repository/__tests__/orders.repository.test.js +211 -0
  126. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +1 -0
  127. package/dist/features/payments/repository/__tests__/payout.repository.test.js +292 -0
  128. package/dist/features/products/api/[id]/route.d.ts +4 -4
  129. package/dist/features/products/api/route.d.ts +2 -2
  130. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +1 -0
  131. package/dist/features/products/repository/__tests__/product-features.repository.test.js +329 -0
  132. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +1 -0
  133. package/dist/features/products/repository/__tests__/products.repository.test.js +607 -0
  134. package/dist/features/products/schemas/firestore.d.ts +15 -1
  135. package/dist/features/products/schemas/index.d.ts +12 -12
  136. package/dist/features/products/schemas/index.js +4 -2
  137. package/dist/features/products/types/index.d.ts +1 -1
  138. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +1 -0
  139. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +219 -0
  140. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +1 -0
  141. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +480 -0
  142. package/dist/features/reviews/api/[id]/route.d.ts +4 -4
  143. package/dist/features/reviews/api/route.d.ts +2 -2
  144. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +1 -0
  145. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +327 -0
  146. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +1 -0
  147. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +385 -0
  148. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +1 -0
  149. package/dist/features/search/repository/__tests__/search.repository.test.js +369 -0
  150. package/dist/features/seller/api/coupons/route.d.ts +2 -2
  151. package/dist/features/seller/api/offers/route.d.ts +2 -2
  152. package/dist/features/seller/api/products/route.d.ts +2 -2
  153. package/dist/features/seller/api/store/route.d.ts +2 -2
  154. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +1 -0
  155. package/dist/features/seller/repository/__tests__/offer.repository.test.js +458 -0
  156. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +1 -0
  157. package/dist/features/stores/repository/__tests__/store.repository.test.js +261 -0
  158. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +1 -0
  159. package/dist/features/support/repository/__tests__/support.repository.test.js +312 -0
  160. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +1 -0
  161. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +139 -0
  162. package/dist/index.d.ts +14 -0
  163. package/dist/index.js +17 -0
  164. package/dist/next/api/routeHandler.d.ts +1 -1
  165. package/dist/next/routing/route-map.d.ts +13 -0
  166. package/dist/next/routing/route-map.js +6 -0
  167. package/dist/repositories/index.d.ts +1 -0
  168. package/dist/repositories/index.js +2 -0
  169. package/dist/security/index.d.ts +1 -1
  170. package/dist/security/index.js +1 -1
  171. package/dist/security/pii-schemas.d.ts +2 -0
  172. package/dist/security/pii-schemas.js +6 -0
  173. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  174. package/dist/seed/events-seed-data.js +85 -2
  175. package/dist/seed/grouped-listings-seed-data.d.ts +3 -1
  176. package/dist/seed/index.d.ts +1 -0
  177. package/dist/seed/index.js +1 -0
  178. package/dist/seed/lottery-entries-seed-data.d.ts +2 -0
  179. package/dist/seed/lottery-entries-seed-data.js +108 -0
  180. package/dist/seed/manifest.js +1 -0
  181. package/dist/seed/products-preorders-seed-data.d.ts +3 -1
  182. package/dist/server.d.ts +6 -0
  183. package/dist/server.js +6 -0
  184. package/dist/styles.css +1 -1
  185. package/dist/tailwind-utilities.css +1 -1
  186. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { makeMockDb, makeSnap } from "../../../../../tests/helpers/mock-firestore";
3
+ const { db, mockDocRef, mockCollection, mockTxn } = makeMockDb();
4
+ vi.mock("../../../../providers/db-firebase", () => ({
5
+ getAdminDb: () => db,
6
+ }));
7
+ vi.mock("../../../../monitoring", () => ({
8
+ serverLogger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
9
+ }));
10
+ import { UserWishlistRepository, WishlistFullError } from "../user-wishlist.repository";
11
+ import { WISHLIST_MAX } from "../../../../constants/limits";
12
+ const repo = new UserWishlistRepository();
13
+ function makeItems(count) {
14
+ return Array.from({ length: count }, (_, i) => ({
15
+ productId: `product-${i}`,
16
+ addedAt: new Date(),
17
+ }));
18
+ }
19
+ beforeEach(() => {
20
+ vi.clearAllMocks();
21
+ // Reset collection chain so tests that override db.collection don't leak
22
+ db.collection.mockReturnValue(mockCollection);
23
+ mockCollection.doc.mockReturnValue(mockDocRef);
24
+ // Default: runTransaction calls through
25
+ db.runTransaction.mockImplementation(async (fn) => fn(mockTxn));
26
+ // Default: doc.get returns non-existent snap
27
+ mockDocRef.get.mockResolvedValue(makeSnap(null));
28
+ mockDocRef.set.mockResolvedValue(undefined);
29
+ mockTxn.get.mockResolvedValue(makeSnap(null));
30
+ mockTxn.set.mockResolvedValue(undefined);
31
+ });
32
+ describe("UserWishlistRepository.addItem", () => {
33
+ it("adds first item: count = 1, no error", async () => {
34
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "user-1", items: [], updatedAt: new Date() }));
35
+ const count = await repo.addItem("user-1", "product-new");
36
+ expect(count).toBe(1);
37
+ expect(mockTxn.set).toHaveBeenCalledOnce();
38
+ });
39
+ it("19 items → adds item, count = 20, no error", async () => {
40
+ const items = makeItems(19);
41
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
42
+ const count = await repo.addItem("u", "product-20");
43
+ expect(count).toBe(20);
44
+ });
45
+ it("20 items + new productId → throws WishlistFullError with current=20, limit=20", async () => {
46
+ const items = makeItems(WISHLIST_MAX);
47
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
48
+ await expect(repo.addItem("u", "product-new")).rejects.toBeInstanceOf(WishlistFullError);
49
+ const err = await repo.addItem("u", "product-new").catch((e) => e);
50
+ if (err instanceof WishlistFullError) {
51
+ expect(err.current).toBe(WISHLIST_MAX);
52
+ expect(err.limit).toBe(WISHLIST_MAX);
53
+ }
54
+ });
55
+ it("20 items + same productId (existing) → idempotent no-op, returns existing count", async () => {
56
+ const items = makeItems(WISHLIST_MAX);
57
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
58
+ const count = await repo.addItem("u", "product-0"); // already in list
59
+ expect(count).toBe(WISHLIST_MAX);
60
+ expect(mockTxn.set).not.toHaveBeenCalled();
61
+ });
62
+ it("5 items + existing productId → idempotent no-op, count remains 5", async () => {
63
+ const items = makeItems(5);
64
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
65
+ const count = await repo.addItem("u", "product-3"); // already in list
66
+ expect(count).toBe(5);
67
+ expect(mockTxn.set).not.toHaveBeenCalled();
68
+ });
69
+ it("uses db.runTransaction for every add", async () => {
70
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items: [], updatedAt: new Date() }));
71
+ await repo.addItem("u", "product-x");
72
+ expect(db.runTransaction).toHaveBeenCalledOnce();
73
+ });
74
+ it("stores productType in the item", async () => {
75
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items: [], updatedAt: new Date() }));
76
+ await repo.addItem("u", "product-x", { productType: "auction" });
77
+ const setCall = mockTxn.set.mock.calls[0][1];
78
+ expect(setCall.items[0].productType).toBe("auction");
79
+ });
80
+ });
81
+ describe("UserWishlistRepository.removeItem", () => {
82
+ it("removes existing productId, count decrements", async () => {
83
+ const items = [
84
+ { productId: "product-0", addedAt: new Date() },
85
+ { productId: "product-1", addedAt: new Date() },
86
+ ];
87
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
88
+ await repo.removeItem("u", "product-0");
89
+ const setCall = mockTxn.set.mock.calls[0][1];
90
+ expect(setCall.items).toHaveLength(1);
91
+ expect(setCall.items[0].productId).toBe("product-1");
92
+ });
93
+ it("non-existent productId → no-op, set not called", async () => {
94
+ const items = [{ productId: "product-0", addedAt: new Date() }];
95
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
96
+ await repo.removeItem("u", "product-xxx");
97
+ expect(mockTxn.set).not.toHaveBeenCalled();
98
+ });
99
+ it("uses db.runTransaction", async () => {
100
+ mockTxn.get.mockResolvedValue(makeSnap({ userId: "u", items: [], updatedAt: new Date() }));
101
+ await repo.removeItem("u", "product-x");
102
+ expect(db.runTransaction).toHaveBeenCalledOnce();
103
+ });
104
+ });
105
+ describe("UserWishlistRepository.isInWishlist", () => {
106
+ it("productId in items array → returns true", async () => {
107
+ const items = [{ productId: "product-0", addedAt: new Date() }];
108
+ // First get: wishlist doc; second get: product exists check in filterExistingProducts
109
+ mockDocRef.get
110
+ .mockResolvedValueOnce(makeSnap({ userId: "u", items, updatedAt: new Date() }))
111
+ .mockResolvedValue(makeSnap({ id: "product-0" }, "product-0"));
112
+ const result = await repo.isInWishlist("u", "product-0");
113
+ expect(result).toBe(true);
114
+ });
115
+ it("productId not in items array → returns false", async () => {
116
+ mockDocRef.get.mockResolvedValue(makeSnap({ userId: "u", items: [], updatedAt: new Date() }));
117
+ const result = await repo.isInWishlist("u", "product-xxx");
118
+ expect(result).toBe(false);
119
+ });
120
+ });
121
+ describe("UserWishlistRepository.countByUser", () => {
122
+ it("returns items.length from stored document", async () => {
123
+ const items = makeItems(7);
124
+ mockDocRef.get.mockResolvedValue(makeSnap({ userId: "u", items, updatedAt: new Date() }));
125
+ const count = await repo.countByUser("u");
126
+ expect(count).toBe(7);
127
+ });
128
+ it("returns 0 for user with no document", async () => {
129
+ mockDocRef.get.mockResolvedValue(makeSnap(null));
130
+ const count = await repo.countByUser("u");
131
+ expect(count).toBe(0);
132
+ });
133
+ });
134
+ describe("UserWishlistRepository.clearWishlist", () => {
135
+ it("sets items: [] without deleting the document", async () => {
136
+ await repo.clearWishlist("u");
137
+ expect(mockDocRef.set).toHaveBeenCalledWith(expect.objectContaining({ items: [] }));
138
+ });
139
+ });
package/dist/index.d.ts CHANGED
@@ -444,6 +444,7 @@ export { Can } from "./security/index";
444
444
  export { DEFAULT_ROLES } from "./security/index";
445
445
  export { ENC_PREFIX } from "./security/index";
446
446
  export { EVENT_ENTRY_PII_FIELDS } from "./security/index";
447
+ export { LOTTERY_ENTRY_PII_FIELDS } from "./security/index";
447
448
  export { HMAC_PREFIX } from "./security/index";
448
449
  export { NEWSLETTER_PII_FIELDS } from "./security/index";
449
450
  export { NEWSLETTER_PII_INDEX_MAP } from "./security/index";
@@ -1775,6 +1776,8 @@ export type { AdminEventEditorViewProps } from "./features/events/index";
1775
1776
  export { EVENTS_COLLECTION } from "./features/events/index";
1776
1777
  export { EVENT_ADMIN_SORT_OPTIONS } from "./features/events/index";
1777
1778
  export { EVENT_ENTRIES_COLLECTION } from "./features/events/index";
1779
+ export { LOTTERY_ENTRIES_COLLECTION } from "./features/lottery/schemas/firestore";
1780
+ export { lotteryEntriesSeedData } from "./seed/index";
1778
1781
  export { EVENT_ENTRY_FIELDS } from "./features/events/index";
1779
1782
  export { EVENT_ENTRY_INDEXED_FIELDS } from "./features/events/index";
1780
1783
  export { EVENT_FIELDS } from "./features/events/index";
@@ -1796,6 +1799,17 @@ export { EventRaffleWinnerView } from "./features/events/index";
1796
1799
  export type { EventRaffleWinnerViewProps } from "./features/events/index";
1797
1800
  export { SpinWheelView } from "./features/events/index";
1798
1801
  export type { SpinWheelViewProps } from "./features/events/index";
1802
+ export { LotterySlotGrid } from "./_internal/client/features/lottery/LotterySlotGrid";
1803
+ export { LotteryPullForm } from "./_internal/client/features/lottery/LotteryPullForm";
1804
+ export { LotteryListView } from "./_internal/client/features/lottery/LotteryListView";
1805
+ export { LotteryDetailView } from "./_internal/client/features/lottery/LotteryDetailView";
1806
+ export { LotteryEntriesView } from "./_internal/client/features/lottery/LotteryEntriesView";
1807
+ export { LotteryAdminSlotView } from "./_internal/client/features/lottery/LotteryAdminSlotView";
1808
+ export { LotteryAdminEditView } from "./_internal/client/features/lottery/LotteryAdminEditView";
1809
+ export { PrizeDrawLotteryDetailView } from "./_internal/client/features/lottery/PrizeDrawLotteryDetailView";
1810
+ export type { LotteryConfig, LotterySlot, ClientLotterySlot, ClientLotteryConfig, LotteryPricingMode, LotteryEntryStatus } from "./features/lottery/types";
1811
+ export { LotteryError, computeWeight, pickWeightedSlot, assignSlotWeights } from "./features/lottery/types";
1812
+ export type { LotteryEntryDocument } from "./features/lottery/schemas/firestore";
1799
1813
  export type { SpinPrize } from "./features/events/index";
1800
1814
  export { EventsListView } from "./features/events/index";
1801
1815
  export { EventsIndexListing } from "./features/events/index";
package/dist/index.js CHANGED
@@ -784,6 +784,8 @@ export { ENC_PREFIX } from "./security/index";
784
784
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
785
785
  // EVENT_ENTRY_PII_FIELDS - Constant used across modules.
786
786
  export { EVENT_ENTRY_PII_FIELDS } from "./security/index";
787
+ // LOTTERY_ENTRY_PII_FIELDS - PII fields for lottery entries.
788
+ export { LOTTERY_ENTRY_PII_FIELDS } from "./security/index";
787
789
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
788
790
  // HMAC_PREFIX - Constant used across modules.
789
791
  export { HMAC_PREFIX } from "./security/index";
@@ -1247,6 +1249,7 @@ export { claimedCouponsSeedData } from "./seed/index";
1247
1249
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1248
1250
  // eventEntriesSeedData - Model for event entries seed data.
1249
1251
  export { eventEntriesSeedData } from "./seed/index";
1252
+ // lotteryEntriesSeedData already exported above via LOTTERY_ENTRIES_COLLECTION block.
1250
1253
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
1251
1254
  // eventsSeedData - Model for events seed data.
1252
1255
  export { eventsSeedData } from "./seed/index";
@@ -3382,6 +3385,10 @@ export { EVENT_ADMIN_SORT_OPTIONS } from "./features/events/index";
3382
3385
  // [SCHEMA]-Schema / data-shape constant â€" Zod validator, default-value object, or Firestore collection/field name constant.
3383
3386
  // EVENT_ENTRIES_COLLECTION - Constant used across modules.
3384
3387
  export { EVENT_ENTRIES_COLLECTION } from "./features/events/index";
3388
+ // LOTTERY_ENTRIES_COLLECTION - New lotteryEntries collection constant.
3389
+ export { LOTTERY_ENTRIES_COLLECTION } from "./features/lottery/schemas/firestore";
3390
+ // lotteryEntriesSeedData - Seed data for the lotteryEntries collection.
3391
+ export { lotteryEntriesSeedData } from "./seed/index";
3385
3392
  // [SCHEMA]-Schema / data-shape constant â€" Zod validator, default-value object, or Firestore collection/field name constant.
3386
3393
  // EVENT_ENTRY_FIELDS - Constant used across modules.
3387
3394
  export { EVENT_ENTRY_FIELDS } from "./features/events/index";
@@ -3436,6 +3443,16 @@ export { EventStatusBadge } from "./features/events/index";
3436
3443
  export { EventRaffleWinnerView } from "./features/events/index";
3437
3444
  // SpinWheelView - Spin-the-wheel client component for spin-wheel events.
3438
3445
  export { SpinWheelView } from "./features/events/index";
3446
+ // Lottery feature — client components
3447
+ export { LotterySlotGrid } from "./_internal/client/features/lottery/LotterySlotGrid";
3448
+ export { LotteryPullForm } from "./_internal/client/features/lottery/LotteryPullForm";
3449
+ export { LotteryListView } from "./_internal/client/features/lottery/LotteryListView";
3450
+ export { LotteryDetailView } from "./_internal/client/features/lottery/LotteryDetailView";
3451
+ export { LotteryEntriesView } from "./_internal/client/features/lottery/LotteryEntriesView";
3452
+ export { LotteryAdminSlotView } from "./_internal/client/features/lottery/LotteryAdminSlotView";
3453
+ export { LotteryAdminEditView } from "./_internal/client/features/lottery/LotteryAdminEditView";
3454
+ export { PrizeDrawLotteryDetailView } from "./_internal/client/features/lottery/PrizeDrawLotteryDetailView";
3455
+ export { LotteryError, computeWeight, pickWeightedSlot, assignSlotWeights } from "./features/lottery/types";
3439
3456
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3440
3457
  // EventsListView - Component for events list view.
3441
3458
  export { EventsListView } from "./features/events/index";
@@ -61,7 +61,7 @@ interface RouteHandlerOptions<TInput = unknown, TParams = Record<string, string>
61
61
  requestId: string;
62
62
  }) => Promise<Response>;
63
63
  }
64
- export declare function createRouteHandler<TInput = unknown, TParams = Record<string, string>>(options: RouteHandlerOptions<TInput, TParams>): (request: Request, context: {
64
+ export declare function createRouteHandler<TInput = unknown, TParams = Record<string, string>>(options: RouteHandlerOptions<TInput, TParams>): (request: Request, context?: {
65
65
  params: Promise<TParams>;
66
66
  }) => Promise<Response>;
67
67
  export {};
@@ -81,6 +81,8 @@ export declare const DEFAULT_ROUTE_MAP: {
81
81
  readonly EVENT_PARTICIPATE: (id: string) => string;
82
82
  readonly EVENT_LEADERBOARD: (id: string) => string;
83
83
  readonly EVENT_WINNER: (id: string) => string;
84
+ readonly LOTTERIES: "/lottery";
85
+ readonly LOTTERY_DETAIL: (id: string) => string;
84
86
  readonly SUBLISTING_CATEGORIES: "/sublisting-categories";
85
87
  readonly SUBLISTING_CATEGORY: (slug: string) => string;
86
88
  readonly SUPPORT: "/support";
@@ -187,6 +189,7 @@ export declare const DEFAULT_ROUTE_MAP: {
187
189
  readonly PRIZE_DRAWS: "/store/prize-draws";
188
190
  readonly PRIZE_DRAWS_NEW: "/store/prize-draws/new";
189
191
  readonly PRIZE_DRAWS_EDIT: (id: string) => string;
192
+ readonly PRIZE_DRAW_ENTRIES: (id: string) => string;
190
193
  readonly PRODUCT_CODES: (id: string) => string;
191
194
  readonly CLASSIFIED: "/store/classified";
192
195
  readonly CLASSIFIED_NEW: "/store/classified/new";
@@ -301,6 +304,9 @@ export declare const DEFAULT_ROUTE_MAP: {
301
304
  readonly BUNDLES_EDIT: (id: string) => string;
302
305
  readonly PRIZE_DRAWS: "/admin/prize-draws";
303
306
  readonly PRIZE_DRAWS_EDIT: (id: string) => string;
307
+ readonly PRIZE_DRAWS_ENTRIES: (id: string) => string;
308
+ readonly LOTTERIES: "/admin/lotteries";
309
+ readonly LOTTERY_ENTRIES: (id: string) => string;
304
310
  readonly TEAM: "/admin/team";
305
311
  readonly SUPPORT_TICKETS: "/admin/support-tickets";
306
312
  readonly SUPPORT_TICKET_BY_ID: (id: string) => string;
@@ -411,6 +417,8 @@ export declare const ROUTES: {
411
417
  readonly EVENT_PARTICIPATE: (id: string) => string;
412
418
  readonly EVENT_LEADERBOARD: (id: string) => string;
413
419
  readonly EVENT_WINNER: (id: string) => string;
420
+ readonly LOTTERIES: "/lottery";
421
+ readonly LOTTERY_DETAIL: (id: string) => string;
414
422
  readonly SUBLISTING_CATEGORIES: "/sublisting-categories";
415
423
  readonly SUBLISTING_CATEGORY: (slug: string) => string;
416
424
  readonly SUPPORT: "/support";
@@ -517,6 +525,7 @@ export declare const ROUTES: {
517
525
  readonly PRIZE_DRAWS: "/store/prize-draws";
518
526
  readonly PRIZE_DRAWS_NEW: "/store/prize-draws/new";
519
527
  readonly PRIZE_DRAWS_EDIT: (id: string) => string;
528
+ readonly PRIZE_DRAW_ENTRIES: (id: string) => string;
520
529
  readonly PRODUCT_CODES: (id: string) => string;
521
530
  readonly CLASSIFIED: "/store/classified";
522
531
  readonly CLASSIFIED_NEW: "/store/classified/new";
@@ -631,6 +640,9 @@ export declare const ROUTES: {
631
640
  readonly BUNDLES_EDIT: (id: string) => string;
632
641
  readonly PRIZE_DRAWS: "/admin/prize-draws";
633
642
  readonly PRIZE_DRAWS_EDIT: (id: string) => string;
643
+ readonly PRIZE_DRAWS_ENTRIES: (id: string) => string;
644
+ readonly LOTTERIES: "/admin/lotteries";
645
+ readonly LOTTERY_ENTRIES: (id: string) => string;
634
646
  readonly TEAM: "/admin/team";
635
647
  readonly SUPPORT_TICKETS: "/admin/support-tickets";
636
648
  readonly SUPPORT_TICKET_BY_ID: (id: string) => string;
@@ -713,6 +725,7 @@ export declare const SELLER_ROUTES: {
713
725
  readonly PRIZE_DRAWS: "/store/prize-draws";
714
726
  readonly PRIZE_DRAWS_NEW: "/store/prize-draws/new";
715
727
  readonly PRIZE_DRAWS_EDIT: (id: string) => string;
728
+ readonly PRIZE_DRAW_ENTRIES: (id: string) => string;
716
729
  readonly PRODUCT_CODES: (id: string) => string;
717
730
  readonly CLASSIFIED: "/store/classified";
718
731
  readonly CLASSIFIED_NEW: "/store/classified/new";
@@ -69,6 +69,8 @@ export const DEFAULT_ROUTE_MAP = {
69
69
  EVENT_PARTICIPATE: (id) => `/events/${id}/participate`,
70
70
  EVENT_LEADERBOARD: (id) => `/events/${id}/leaderboard`,
71
71
  EVENT_WINNER: (id) => `/events/${id}/winner`,
72
+ LOTTERIES: "/lottery",
73
+ LOTTERY_DETAIL: (id) => `/lottery/${id}`,
72
74
  SUBLISTING_CATEGORIES: "/sublisting-categories",
73
75
  SUBLISTING_CATEGORY: (slug) => `/sublisting-categories/${slug}`,
74
76
  SUPPORT: "/support",
@@ -176,6 +178,7 @@ export const DEFAULT_ROUTE_MAP = {
176
178
  PRIZE_DRAWS: "/store/prize-draws",
177
179
  PRIZE_DRAWS_NEW: "/store/prize-draws/new",
178
180
  PRIZE_DRAWS_EDIT: (id) => `/store/prize-draws/${id}/edit`,
181
+ PRIZE_DRAW_ENTRIES: (id) => `/store/prize-draws/${id}/entries`,
179
182
  PRODUCT_CODES: (id) => `/store/products/${id}/codes`,
180
183
  // SB-UNI-R — classified / digital-code / live
181
184
  CLASSIFIED: "/store/classified",
@@ -295,6 +298,9 @@ export const DEFAULT_ROUTE_MAP = {
295
298
  BUNDLES_EDIT: (id) => `/admin/bundles/${id}/edit`,
296
299
  PRIZE_DRAWS: "/admin/prize-draws",
297
300
  PRIZE_DRAWS_EDIT: (id) => `/admin/prize-draws/${id}/edit`,
301
+ PRIZE_DRAWS_ENTRIES: (id) => `/admin/prize-draws/${id}/entries`,
302
+ LOTTERIES: "/admin/lotteries",
303
+ LOTTERY_ENTRIES: (id) => `/admin/lotteries/${id}/entries`,
298
304
  TEAM: "/admin/team",
299
305
  SUPPORT_TICKETS: "/admin/support-tickets",
300
306
  SUPPORT_TICKET_BY_ID: (id) => `/admin/support-tickets/${id}`,
@@ -49,3 +49,4 @@ export type { ProductTemplateDocument, ProductTemplateCreateInput, ProductTempla
49
49
  export { ProductFeaturesRepository, productFeaturesRepository, } from "../features/products/repository/product-features.repository";
50
50
  export type { ProductFeatureListFilter } from "../features/products/repository/product-features.repository";
51
51
  export { loadProductFeaturesForStore } from "../features/products/repository/loadProductFeatures";
52
+ export { LotteryEntryRepository, lotteryEntryRepository, } from "../features/lottery/repository/lottery-entry.repository";
@@ -59,3 +59,5 @@ export { loadProductFeaturesForStore } from "../features/products/repository/loa
59
59
  // SB-UNI-V — BundlesRepository deleted; bundles live on categoriesRepository
60
60
  // with categoryType:"bundle". See features/categories/repository for the
61
61
  // listByType / findBySlugAndType helpers.
62
+ // Lottery entries repository
63
+ export { LotteryEntryRepository, lotteryEntryRepository, } from "../features/lottery/repository/lottery-entry.repository";
@@ -5,7 +5,7 @@ export { requireAuth, requireRole, requireOwnership, requireEmailVerified, requi
5
5
  export type { UserRole } from "./authorization";
6
6
  export { redactPii, safeDisplayName, safeDisplayEmail, maskIp } from "./pii-redact";
7
7
  export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, isPiiEncrypted, piiBlindIndex, addPiiIndices, getPiiConfigError, encryptShippingAddress, decryptShippingAddress, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, maskName, maskEmail, maskPublicReview, maskPublicBid, maskPublicEventEntry, maskOfferForSeller, ENC_PREFIX, HMAC_PREFIX, } from "./pii-encrypt";
8
- export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, NEWSLETTER_PII_FIELDS, NEWSLETTER_PII_INDEX_MAP, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, CHAT_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, } from "./pii-schemas";
8
+ export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, NEWSLETTER_PII_FIELDS, NEWSLETTER_PII_INDEX_MAP, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, CHAT_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, LOTTERY_ENTRY_PII_FIELDS, } from "./pii-schemas";
9
9
  export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, } from "./settings-encryption";
10
10
  export type { Permission, RoleDefinition, RbacConfig, ResolvedUser, RbacHookReturn, } from "./rbac";
11
11
  export { DEFAULT_ROLES, resolvePermissions, hasPermission, hasAllPermissions, hasAnyPermission, createRbacHook, Can, createRequirePermission, createRequirePermissionSync, createRbacMiddleware, } from "./rbac";
@@ -3,6 +3,6 @@ export { rateLimit, applyRateLimit, rateLimitByIdentifier, RateLimitPresets, cle
3
3
  export { requireAuth, requireRole, requireOwnership, requireEmailVerified, requireActiveAccount, canChangeRole, getRoleLevel, } from "./authorization";
4
4
  export { redactPii, safeDisplayName, safeDisplayEmail, maskIp } from "./pii-redact";
5
5
  export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPiiFields, encryptPii, decryptPii, isPiiEncrypted, piiBlindIndex, addPiiIndices, getPiiConfigError, encryptShippingAddress, decryptShippingAddress, encryptPayoutDetails, decryptPayoutDetails, encryptShippingConfig, decryptShippingConfig, encryptPayoutBankAccount, decryptPayoutBankAccount, maskName, maskEmail, maskPublicReview, maskPublicBid, maskPublicEventEntry, maskOfferForSeller, ENC_PREFIX, HMAC_PREFIX, } from "./pii-encrypt";
6
- export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, NEWSLETTER_PII_FIELDS, NEWSLETTER_PII_INDEX_MAP, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, CHAT_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, } from "./pii-schemas";
6
+ export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, NEWSLETTER_PII_FIELDS, NEWSLETTER_PII_INDEX_MAP, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, CHAT_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, LOTTERY_ENTRY_PII_FIELDS, } from "./pii-schemas";
7
7
  export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, } from "./settings-encryption";
8
8
  export { DEFAULT_ROLES, resolvePermissions, hasPermission, hasAllPermissions, hasAnyPermission, createRbacHook, Can, createRequirePermission, createRequirePermissionSync, createRbacMiddleware, } from "./rbac";
@@ -36,5 +36,7 @@ export declare const OFFER_PII_FIELDS: readonly ["buyerName", "buyerEmail", "sel
36
36
  export declare const CHAT_PII_FIELDS: readonly ["buyerName", "sellerName"];
37
37
  /** PII fields in event entries */
38
38
  export declare const EVENT_ENTRY_PII_FIELDS: readonly ["userDisplayName", "userEmail", "ipAddress"];
39
+ /** PII fields in lottery entries */
40
+ export declare const LOTTERY_ENTRY_PII_FIELDS: readonly ["userPhone", "userEmail", "userDisplayName"];
39
41
  /** Store OAuth bearer tokens — encrypted via SETTINGS_ENCRYPTION_KEY */
40
42
  export declare const STORE_SECRET_FIELDS: readonly ["whatsappConfig.accessToken"];
@@ -60,5 +60,11 @@ export const EVENT_ENTRY_PII_FIELDS = [
60
60
  "userEmail",
61
61
  "ipAddress",
62
62
  ];
63
+ /** PII fields in lottery entries */
64
+ export const LOTTERY_ENTRY_PII_FIELDS = [
65
+ "userPhone",
66
+ "userEmail",
67
+ "userDisplayName",
68
+ ];
63
69
  /** Store OAuth bearer tokens — encrypted via SETTINGS_ENCRYPTION_KEY */
64
70
  export const STORE_SECRET_FIELDS = ["whatsappConfig.accessToken"];
@@ -6,7 +6,7 @@
6
6
  * the actual collection-specific seeding logic (800+ lines with PII encryption,
7
7
  * Auth user creation, subcollection handling, etc.).
8
8
  */
9
- export type SeedCollectionName = "users" | "addresses" | "categories" | "stores" | "products" | "orders" | "reviews" | "bids" | "coupons" | "carousels" | "carouselSlides" | "homepageSections" | "siteSettings" | "faqs" | "notifications" | "payouts" | "blogPosts" | "events" | "eventEntries" | "sessions" | "carts" | "wishlists" | "history" | "conversations" | "groupedListings" | "scammerProfiles" | "supportTickets" | "productFeatures" | "offers" | "couponUsage" | "claimedCoupons" | "payoutMethods" | "shippingConfigs" | "analyticsCards" | "analyticsAlerts" | "storeCategories" | "listingTemplates" | "moderationQueue" | "reports" | "itemRequests" | "storeWhatsAppConfig" | "storeGoogleConfig" | "roleOverrides" | "customRoles" | "adminNotifications";
9
+ export type SeedCollectionName = "users" | "addresses" | "categories" | "stores" | "products" | "orders" | "reviews" | "bids" | "coupons" | "carousels" | "carouselSlides" | "homepageSections" | "siteSettings" | "faqs" | "notifications" | "payouts" | "blogPosts" | "events" | "eventEntries" | "sessions" | "carts" | "wishlists" | "history" | "conversations" | "groupedListings" | "scammerProfiles" | "supportTickets" | "productFeatures" | "offers" | "couponUsage" | "claimedCoupons" | "payoutMethods" | "shippingConfigs" | "analyticsCards" | "analyticsAlerts" | "storeCategories" | "listingTemplates" | "moderationQueue" | "reports" | "itemRequests" | "storeWhatsAppConfig" | "storeGoogleConfig" | "roleOverrides" | "customRoles" | "adminNotifications" | "lotteryEntries";
10
10
  export interface SeedOperationResult {
11
11
  success?: boolean;
12
12
  message: string;
@@ -1,6 +1,6 @@
1
1
  /*
2
- * WHY: Seeds 8 YGO-themed events covering all event types (poll, survey, sale, raffle, spin_wheel, feedback, offer).
3
- * WHAT: 2 upcoming + 4 active + 2 ended. Includes raffle (open + drawn), spin wheel, poll, survey, feedback, sale, offer.
2
+ * WHY: Seeds 10 YGO-themed events covering all event types (poll, survey, sale, raffle, spin_wheel, feedback, offer, lottery).
3
+ * WHAT: 2 upcoming + 4 active + 2 ended + 2 lottery (1 active, 1 draft). Includes raffle (open + drawn), spin wheel, poll, survey, feedback, sale, offer.
4
4
  *
5
5
  * EXPORTS:
6
6
  * eventsSeedData — Array of EventDocument for seed runner
@@ -217,6 +217,89 @@ export const eventsSeedData = [
217
217
  createdAt: daysAgo(35),
218
218
  updatedAt: daysAgo(5),
219
219
  },
220
+ // ── 9. ACTIVE — Lottery: Pokémon Number Draw (July 2026) ─────────────────
221
+ {
222
+ id: "event-pokemon-number-draw-july-2026",
223
+ slug: "pokemon-number-draw-july-2026",
224
+ type: "lottery",
225
+ title: "Pokémon Number Draw — July 2026",
226
+ description: "<p>Choose your lucky slot and win rare Pokémon collectibles! 25 slots available. Each slot is assigned a prize from our collection. First-come, first-served.</p>",
227
+ status: EVENT_FIELDS.STATUS_VALUES.ACTIVE,
228
+ startsAt: daysAgo(2),
229
+ endsAt: daysAhead(5),
230
+ coverImage: { type: "image", url: seedExtMedia("https://upload.wikimedia.org/wikipedia/commons/9/98/International_Pok%C3%A9mon_logo.svg"), alt: "Pok\u00e9mon Number Draw" },
231
+ tags: ["lottery", "pokemon", "prizes"],
232
+ lotteryConfig: {
233
+ totalSlots: 25,
234
+ pricingMode: "variable",
235
+ drawWindowDurationMinutes: 5,
236
+ maxPullsPerTransaction: 1,
237
+ maxPullsPerUser: 1,
238
+ slots: [
239
+ { slotNumber: 1, name: "Charizard Base Set Holo", priceInPaise: 500000, weight: 1, isBooked: true, bookedByUserId: "user-ravi-k", bookedByDisplayName: "Ravi K", bookedByUserLotteryNumber: 1 },
240
+ { slotNumber: 2, name: "Blastoise Base Set Holo", priceInPaise: 300000, weight: 33, isBooked: true, bookedByUserId: "user-priya-s", bookedByDisplayName: "Priya S", bookedByUserLotteryNumber: 2 },
241
+ { slotNumber: 3, name: "Venusaur Base Set Holo", priceInPaise: 250000, weight: 40, isBooked: true, bookedByUserId: "user-arjun-m", bookedByDisplayName: "Arjun M", bookedByUserLotteryNumber: 3 },
242
+ { slotNumber: 4, name: "Pikachu Surfing Promo", priceInPaise: 150000, weight: 66, isBooked: true, bookedByUserId: "user-sneha-p", bookedByDisplayName: "Sneha P", bookedByUserLotteryNumber: 4 },
243
+ { slotNumber: 5, name: "Mewtwo Base Set Holo", priceInPaise: 200000, weight: 50, isBooked: true, bookedByUserId: "user-vikram-r", bookedByDisplayName: "Vikram R", bookedByUserLotteryNumber: 5 },
244
+ { slotNumber: 6, name: "Gengar First Ed. Fossil", priceInPaise: 350000, weight: 28, isBooked: false },
245
+ { slotNumber: 7, name: "Alakazam Base Set Holo", priceInPaise: 80000, weight: 93, isBooked: false },
246
+ { slotNumber: 8, name: "Machamp 1st Ed. Base Set", priceInPaise: 40000, weight: 99, isBooked: false },
247
+ { slotNumber: 9, name: "Clefairy Base Set Holo", priceInPaise: 60000, weight: 95, isBooked: false },
248
+ { slotNumber: 10, name: "Chansey Base Set Holo", priceInPaise: 70000, weight: 94, isBooked: false },
249
+ { slotNumber: 11, name: "Ninetales Base Set Holo", priceInPaise: 100000, weight: 80, isBooked: false },
250
+ { slotNumber: 12, name: "Scyther Jungle Holo", priceInPaise: 50000, weight: 97, isBooked: false },
251
+ { slotNumber: 13, name: "Gyarados Base Set Holo", priceInPaise: 120000, weight: 76, isBooked: false },
252
+ { slotNumber: 14, name: "Lapras Fossil Holo", priceInPaise: 90000, weight: 88, isBooked: false },
253
+ { slotNumber: 15, name: "Zapdos Fossil Holo", priceInPaise: 220000, weight: 45, isBooked: false },
254
+ { slotNumber: 16, name: "Articuno Fossil Holo", priceInPaise: 200000, weight: 50, isBooked: false },
255
+ { slotNumber: 17, name: "Moltres Fossil Holo", priceInPaise: 180000, weight: 55, isBooked: false },
256
+ { slotNumber: 18, name: "Dragonite Base Set Holo", priceInPaise: 400000, weight: 20, isBooked: false },
257
+ { slotNumber: 19, name: "Snorlax Jungle Holo", priceInPaise: 60000, weight: 95, isBooked: false },
258
+ { slotNumber: 20, name: "Jolteon Jungle Holo", priceInPaise: 70000, weight: 94, isBooked: false },
259
+ { slotNumber: 21, name: "Flareon Jungle Holo", priceInPaise: 70000, weight: 94, isBooked: false },
260
+ { slotNumber: 22, name: "Vaporeon Jungle Holo", priceInPaise: 70000, weight: 94, isBooked: false },
261
+ { slotNumber: 23, name: "Espeon Neo Discovery Holo", priceInPaise: 80000, weight: 93, isBooked: false },
262
+ { slotNumber: 24, name: "Umbreon Neo Discovery Holo", priceInPaise: 100000, weight: 80, isBooked: false },
263
+ { slotNumber: 25, name: "Lugia Neo Genesis Holo", priceInPaise: 450000, weight: 10, isBooked: false },
264
+ ],
265
+ },
266
+ stats: { totalEntries: 5, approvedEntries: 5, flaggedEntries: 0 },
267
+ createdBy: "user-admin-letitrip",
268
+ createdAt: daysAgo(3),
269
+ updatedAt: daysAgo(0),
270
+ },
271
+ // ── 10. DRAFT — Lottery: Yu-Gi-Oh! Slot Raffle ───────────────────────────
272
+ {
273
+ id: "event-yugioh-slot-raffle-draft",
274
+ slug: "yugioh-slot-raffle-draft",
275
+ type: "lottery",
276
+ title: "Yu-Gi-Oh! Slot Raffle — Coming Soon",
277
+ description: "<p>10 rare YGO slots up for grabs. Details coming soon!</p>",
278
+ status: EVENT_FIELDS.STATUS_VALUES.DRAFT,
279
+ startsAt: daysAhead(7),
280
+ endsAt: daysAhead(14),
281
+ coverImage: { type: "image", url: seedExtMedia("https://upload.wikimedia.org/wikipedia/en/3/3d/Yu-Gi-Oh%21_Logo.png"), alt: "Yu-Gi-Oh! Slot Raffle" },
282
+ tags: ["lottery", "yugioh", "prizes"],
283
+ lotteryConfig: {
284
+ totalSlots: 10,
285
+ pricingMode: "uniform",
286
+ uniformPriceInPaise: 50000,
287
+ drawWindowDurationMinutes: 10,
288
+ maxPullsPerTransaction: 1,
289
+ maxPullsPerUser: 1,
290
+ slots: Array.from({ length: 10 }, (_, i) => ({
291
+ slotNumber: i + 1,
292
+ name: `Prize Slot ${i + 1}`,
293
+ priceInPaise: 50000,
294
+ weight: 50,
295
+ isBooked: false,
296
+ })),
297
+ },
298
+ stats: { totalEntries: 0, approvedEntries: 0, flaggedEntries: 0 },
299
+ createdBy: "user-admin-letitrip",
300
+ createdAt: daysAgo(1),
301
+ updatedAt: daysAgo(0),
302
+ },
220
303
  ];
221
304
  // ── Event Entries ────────────────────────────────────────────────────────────
222
305
  export const eventEntriesSeedData = [
@@ -31,7 +31,7 @@ export declare const groupedListingsSeedData: {
31
31
  features?: string[] | undefined;
32
32
  shippingInfo?: string | undefined;
33
33
  returnPolicy?: string | undefined;
34
- condition?: "new" | "used" | "refurbished" | "broken" | "graded" | undefined;
34
+ condition?: "new" | "like_new" | "good" | "fair" | "poor" | "used" | "refurbished" | "broken" | "graded" | undefined;
35
35
  insurance?: boolean | undefined;
36
36
  insuranceCost?: number | undefined;
37
37
  shippingPaidBy?: "seller" | "buyer" | undefined;
@@ -102,6 +102,8 @@ export declare const groupedListingsSeedData: {
102
102
  prizeRevealStatus?: "pending" | "open" | "closed" | undefined;
103
103
  prizeRevealDeadlineDays?: number | undefined;
104
104
  prizeGithubFileUrl?: string | undefined;
105
+ prizeDrawMode?: "reveal" | "lottery" | undefined;
106
+ lotteryConfig?: import("..").LotteryConfig | undefined;
105
107
  shipping?: {
106
108
  allowedProviderIds?: string[];
107
109
  overrides?: Array<{
@@ -61,6 +61,7 @@ export type { CouponUsageSeedRecord } from "./coupon-usage-seed-data";
61
61
  export { couponUsageSeedData } from "./coupon-usage-seed-data";
62
62
  export { claimedCouponsSeedData } from "./claimed-coupons-seed-data";
63
63
  export { eventsSeedData, eventEntriesSeedData } from "./events-seed-data";
64
+ export { lotteryEntriesSeedData } from "./lottery-entries-seed-data";
64
65
  export { payoutsSeedData } from "./payouts-seed-data";
65
66
  export { notificationsSeedData } from "./notifications-seed-data";
66
67
  export { blogPostsSeedData } from "./blog-posts-seed-data";
@@ -48,6 +48,7 @@ export { couponsSeedData } from "./coupons-seed-data";
48
48
  export { couponUsageSeedData } from "./coupon-usage-seed-data";
49
49
  export { claimedCouponsSeedData } from "./claimed-coupons-seed-data";
50
50
  export { eventsSeedData, eventEntriesSeedData } from "./events-seed-data";
51
+ export { lotteryEntriesSeedData } from "./lottery-entries-seed-data";
51
52
  export { payoutsSeedData } from "./payouts-seed-data";
52
53
  export { notificationsSeedData } from "./notifications-seed-data";
53
54
  export { blogPostsSeedData } from "./blog-posts-seed-data";
@@ -0,0 +1,2 @@
1
+ import type { LotteryEntryDocument } from "../features/lottery/schemas/firestore";
2
+ export declare const lotteryEntriesSeedData: LotteryEntryDocument[];