@mohasinac/appkit 4.3.2 → 4.4.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 (183) hide show
  1. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +1 -1
  2. package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +1 -1
  3. package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +1 -1
  4. package/dist/_internal/client/features/maintenance/views/ServerErrorDetailView.js +1 -1
  5. package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +1 -1
  6. package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +14 -3
  7. package/dist/_internal/server/jobs/core/assignSpinPrize.js +95 -56
  8. package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +8 -2
  9. package/dist/_internal/shared/actions/action-registry.js +15 -0
  10. package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
  11. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +4 -4
  12. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  13. package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
  14. package/dist/client.d.ts +36 -0
  15. package/dist/client.js +30 -0
  16. package/dist/constants/api-endpoints.d.ts +6 -0
  17. package/dist/constants/api-endpoints.js +2 -0
  18. package/dist/constants/field-names.d.ts +3 -0
  19. package/dist/constants/field-names.js +4 -0
  20. package/dist/features/about/components/DeveloperView.d.ts +16 -0
  21. package/dist/features/about/components/DeveloperView.js +29 -0
  22. package/dist/features/about/index.d.ts +2 -0
  23. package/dist/features/about/index.js +1 -0
  24. package/dist/features/account/schemas/index.d.ts +16 -16
  25. package/dist/features/addresses/schemas/index.d.ts +8 -8
  26. package/dist/features/admin/components/AdminAddressesView.js +1 -1
  27. package/dist/features/admin/components/AdminAllEventEntriesView.js +2 -2
  28. package/dist/features/admin/components/AdminArtView.js +1 -1
  29. package/dist/features/admin/components/AdminBidsView.js +2 -2
  30. package/dist/features/admin/components/AdminBlogView.js +2 -2
  31. package/dist/features/admin/components/AdminBrandsView.js +2 -2
  32. package/dist/features/admin/components/AdminBundlesView.js +2 -2
  33. package/dist/features/admin/components/AdminCartsView.js +2 -2
  34. package/dist/features/admin/components/AdminCategoriesView.js +2 -2
  35. package/dist/features/admin/components/AdminClassifiedView.js +1 -1
  36. package/dist/features/admin/components/AdminContactView.js +2 -2
  37. package/dist/features/admin/components/AdminCouponsView.js +2 -2
  38. package/dist/features/admin/components/AdminDigitalCodesView.js +1 -1
  39. package/dist/features/admin/components/AdminFaqsView.js +2 -2
  40. package/dist/features/admin/components/AdminFeaturesView.js +1 -1
  41. package/dist/features/admin/components/AdminGroupedListingsView.js +1 -1
  42. package/dist/features/admin/components/AdminHistoryView.js +1 -1
  43. package/dist/features/admin/components/AdminLiveView.js +1 -1
  44. package/dist/features/admin/components/AdminNewsletterView.js +2 -2
  45. package/dist/features/admin/components/AdminNotificationsView.js +2 -2
  46. package/dist/features/admin/components/AdminOrdersView.js +2 -2
  47. package/dist/features/admin/components/AdminPaymentMethodsView.js +1 -1
  48. package/dist/features/admin/components/AdminPayoutsView.js +2 -2
  49. package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -2
  50. package/dist/features/admin/components/AdminProductsView.js +2 -2
  51. package/dist/features/admin/components/AdminReturnRequestsView.js +1 -1
  52. package/dist/features/admin/components/AdminReviewsView.js +2 -2
  53. package/dist/features/admin/components/AdminScammersView.js +2 -2
  54. package/dist/features/admin/components/AdminSessionsView.js +2 -2
  55. package/dist/features/admin/components/AdminStickersView.js +1 -1
  56. package/dist/features/admin/components/AdminStoreAddressesView.js +1 -1
  57. package/dist/features/admin/components/AdminStoresView.js +2 -2
  58. package/dist/features/admin/components/AdminSublistingCategoriesView.js +1 -1
  59. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
  60. package/dist/features/admin/components/AdminTeamView.js +2 -2
  61. package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
  62. package/dist/features/admin/components/AdminUsersView.js +2 -2
  63. package/dist/features/admin/components/AdminWishlistsView.js +1 -1
  64. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
  65. package/dist/features/auth/hooks/useAuth.d.ts +1 -1
  66. package/dist/features/blog/actions/blog-actions.d.ts +14 -14
  67. package/dist/features/blog/schemas/index.d.ts +14 -14
  68. package/dist/features/cart/hooks/useAddToCart.d.ts +6 -2
  69. package/dist/features/cart/hooks/useAddToCart.js +20 -3
  70. package/dist/features/cart/schemas/index.d.ts +3 -3
  71. package/dist/features/cart/utils/pending-ops.d.ts +20 -0
  72. package/dist/features/cart/utils/pending-ops.js +22 -0
  73. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
  74. package/dist/features/categories/components/CategoryBundlesListing.js +1 -1
  75. package/dist/features/categories/components/CategoryFilters.js +1 -1
  76. package/dist/features/categories/components/CategoryTree.js +1 -1
  77. package/dist/features/categories/schemas/index.d.ts +16 -16
  78. package/dist/features/events/actions/event-actions.d.ts +21 -1
  79. package/dist/features/events/actions/event-actions.js +85 -3
  80. package/dist/features/events/components/AdminEventEditorView.js +11 -2
  81. package/dist/features/events/components/AdminEventEntriesView.js +37 -4
  82. package/dist/features/events/components/AdminEventsView.js +2 -2
  83. package/dist/features/events/components/EventLeaderboard.d.ts +12 -2
  84. package/dist/features/events/components/EventLeaderboard.js +4 -1
  85. package/dist/features/events/components/EventRafflesSection.js +2 -2
  86. package/dist/features/events/repository/event-entry.repository.d.ts +39 -0
  87. package/dist/features/events/repository/event-entry.repository.js +153 -0
  88. package/dist/features/events/schemas/firestore.d.ts +28 -1
  89. package/dist/features/events/schemas/firestore.js +9 -0
  90. package/dist/features/events/schemas/index.d.ts +13 -13
  91. package/dist/features/events/types/index.d.ts +26 -0
  92. package/dist/features/faq/actions/faq-actions.d.ts +8 -8
  93. package/dist/features/faq/schemas/index.d.ts +22 -22
  94. package/dist/features/grouped/schemas/index.d.ts +2 -2
  95. package/dist/features/homepage/components/AnnouncementBar.d.ts +9 -1
  96. package/dist/features/homepage/components/AnnouncementBar.js +6 -3
  97. package/dist/features/homepage/components/MarketplaceHomepageView.js +2 -2
  98. package/dist/features/homepage/components/SectionCarousel.js +5 -1
  99. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  100. package/dist/features/homepage/schemas/index.d.ts +2 -2
  101. package/dist/features/layout/BottomNavbar.js +8 -6
  102. package/dist/features/lottery/schemas/zod.d.ts +10 -10
  103. package/dist/features/media/MediaVideo.js +11 -3
  104. package/dist/features/orders/schemas/index.d.ts +52 -52
  105. package/dist/features/products/components/CompareOverlay.d.ts +9 -0
  106. package/dist/features/products/components/CompareOverlay.js +28 -3
  107. package/dist/features/products/components/InteractiveProductCard.js +9 -3
  108. package/dist/features/products/components/MakeOfferForm.js +1 -1
  109. package/dist/features/products/components/PlaceBidForm.js +1 -1
  110. package/dist/features/products/components/PrizeDrawCollage.js +1 -1
  111. package/dist/features/products/components/PrizeDrawsSection.js +2 -2
  112. package/dist/features/products/components/ProductDetailActions.js +3 -1
  113. package/dist/features/products/components/ProductGrid.js +1 -1
  114. package/dist/features/products/components/ProductInfo.js +1 -1
  115. package/dist/features/products/components/ProductsIndexListing.js +12 -2
  116. package/dist/features/products/hooks/useRelatedProducts.js +1 -1
  117. package/dist/features/products/schemas/index.d.ts +10 -10
  118. package/dist/features/promotions/schemas/index.d.ts +8 -8
  119. package/dist/features/reviews/schemas/index.d.ts +12 -12
  120. package/dist/features/scams/schemas/index.d.ts +6 -6
  121. package/dist/features/seller/components/CouponInlineSelect.js +1 -1
  122. package/dist/features/seller/components/SellerArtView.js +2 -2
  123. package/dist/features/seller/components/SellerAuctionsView.js +2 -2
  124. package/dist/features/seller/components/SellerBidsView.js +2 -2
  125. package/dist/features/seller/components/SellerBundlesView.js +1 -1
  126. package/dist/features/seller/components/SellerClassifiedView.js +2 -2
  127. package/dist/features/seller/components/SellerCouponsView.js +2 -2
  128. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  129. package/dist/features/seller/components/SellerGroupedListingsView.js +1 -1
  130. package/dist/features/seller/components/SellerLiveView.js +2 -2
  131. package/dist/features/seller/components/SellerOffersView.js +2 -2
  132. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  133. package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
  134. package/dist/features/seller/components/SellerPayoutsView.js +2 -2
  135. package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
  136. package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
  137. package/dist/features/seller/components/SellerProductsView.js +2 -2
  138. package/dist/features/seller/components/SellerShippingConfigsView.js +2 -2
  139. package/dist/features/seller/components/SellerStickersView.js +2 -2
  140. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  141. package/dist/features/seller/components/SublistingInlineSelect.js +1 -1
  142. package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
  143. package/dist/features/seller/schemas/index.d.ts +16 -16
  144. package/dist/features/server-errors/schemas/index.d.ts +4 -4
  145. package/dist/features/shell/StepForm.d.ts +1 -1
  146. package/dist/features/shipments/components/AdminShipmentsView.js +2 -2
  147. package/dist/features/stores/components/StoreProductsView.js +1 -1
  148. package/dist/features/stores/components/StoresIndexListing.js +1 -1
  149. package/dist/features/stores/schemas/index.d.ts +30 -30
  150. package/dist/features/support/schemas/index.d.ts +2 -2
  151. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +68 -1
  152. package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +14 -0
  153. package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +17 -0
  154. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +2 -8
  155. package/dist/features/whatsapp-bot/helpers/whatsapp.js +4 -11
  156. package/dist/features/wishlist/repository/user-wishlist.repository.d.ts +11 -0
  157. package/dist/features/wishlist/repository/user-wishlist.repository.js +33 -0
  158. package/dist/index.d.ts +7 -12
  159. package/dist/index.js +16 -28
  160. package/dist/next/components/ErrorView.js +1 -1
  161. package/dist/next/components/NotFoundView.js +1 -1
  162. package/dist/next/components/UnauthorizedView.js +1 -1
  163. package/dist/next/routing/route-map.d.ts +4 -0
  164. package/dist/next/routing/route-map.js +2 -0
  165. package/dist/react/contexts/SessionContext.d.ts +1 -1
  166. package/dist/react/hooks/use-action-dispatch.d.ts +1 -1
  167. package/dist/react/hooks/useFormStatePreservation.d.ts +1 -1
  168. package/dist/schemas/registry.d.ts +236 -236
  169. package/dist/schemas/webhooks/razorpay.d.ts +100 -100
  170. package/dist/security/index.d.ts +1 -1
  171. package/dist/security/index.js +1 -1
  172. package/dist/security/rate-limit.d.ts +10 -0
  173. package/dist/security/rate-limit.js +13 -1
  174. package/dist/seed/events-seed-data.js +52 -1
  175. package/dist/server.d.ts +6 -0
  176. package/dist/server.js +8 -0
  177. package/dist/styles.css +25 -1
  178. package/dist/tailwind-utilities.css +1 -1
  179. package/dist/ui/components/HorizontalScroller.d.ts +7 -1
  180. package/dist/ui/components/HorizontalScroller.js +2 -2
  181. package/dist/ui/components/HorizontalScroller.style.css +24 -0
  182. package/dist/validation/schemas.d.ts +12 -12
  183. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { sortBy } from "@mohasinac/appkit";
3
+ import { sortBy } from "@mohasinac/appkit/client";
4
4
  import { useState } from "react";
5
5
  import { Div, Heading, Input, Select, SlottedListingView } from "../../../ui";
6
6
  export function StoreProductsView({ storeSlug, labels = {}, renderProducts, renderSearch, renderSort, renderFilters, renderActiveFilters, renderViewToggle, renderPagination, items = [], total = 0, isLoading = false, className = "", }) {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Row, SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit";
3
+ import { Row, SIEVE_OP, Stack, sieveFilter } from "@mohasinac/appkit/client";
4
4
  import { useState, useCallback, useMemo } from "react";
5
5
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { useStores } from "../hooks/useStores";
@@ -412,19 +412,27 @@ export declare const storeFirestoreSchema: z.ZodObject<{
412
412
  }, z.ZodTypeAny, "passthrough">;
413
413
  storeName: string;
414
414
  isPublic: boolean;
415
- storeSlug: string;
416
415
  ownerId: string;
416
+ storeSlug: string;
417
417
  location?: string | undefined;
418
418
  returnPolicy?: string | undefined;
419
+ isFeatured?: boolean | undefined;
420
+ socialLinks?: {
421
+ instagram?: string | undefined;
422
+ facebook?: string | undefined;
423
+ twitter?: string | undefined;
424
+ linkedin?: string | undefined;
425
+ } | undefined;
419
426
  stats?: {
420
427
  itemsSold: number;
421
428
  totalProducts: number;
422
429
  totalReviews: number;
423
430
  averageRating?: number | undefined;
424
431
  } | undefined;
425
- isFeatured?: boolean | undefined;
426
- emiEnabled?: boolean | undefined;
427
- website?: string | undefined;
432
+ storeCategory?: string | undefined;
433
+ storeDescription?: string | undefined;
434
+ storeLogoURL?: string | undefined;
435
+ storeBannerURL?: string | undefined;
428
436
  shippingConfig?: {
429
437
  providers: {
430
438
  type: "custom" | "self-courier" | "store-pickup";
@@ -444,17 +452,9 @@ export declare const storeFirestoreSchema: z.ZodObject<{
444
452
  }[];
445
453
  defaultProviderId: string;
446
454
  } | undefined;
447
- storeCategory?: string | undefined;
448
- storeDescription?: string | undefined;
449
- storeLogoURL?: string | undefined;
450
- storeBannerURL?: string | undefined;
451
455
  bio?: string | undefined;
452
- socialLinks?: {
453
- instagram?: string | undefined;
454
- facebook?: string | undefined;
455
- twitter?: string | undefined;
456
- linkedin?: string | undefined;
457
- } | undefined;
456
+ website?: string | undefined;
457
+ emiEnabled?: boolean | undefined;
458
458
  shippingPolicy?: string | undefined;
459
459
  isVacationMode?: boolean | undefined;
460
460
  vacationMessage?: string | undefined;
@@ -497,19 +497,27 @@ export declare const storeFirestoreSchema: z.ZodObject<{
497
497
  }, z.ZodTypeAny, "passthrough">;
498
498
  storeName: string;
499
499
  isPublic: boolean;
500
- storeSlug: string;
501
500
  ownerId: string;
501
+ storeSlug: string;
502
502
  location?: string | undefined;
503
503
  returnPolicy?: string | undefined;
504
+ isFeatured?: boolean | undefined;
505
+ socialLinks?: {
506
+ instagram?: string | undefined;
507
+ facebook?: string | undefined;
508
+ twitter?: string | undefined;
509
+ linkedin?: string | undefined;
510
+ } | undefined;
504
511
  stats?: {
505
512
  itemsSold: number;
506
513
  totalProducts: number;
507
514
  totalReviews: number;
508
515
  averageRating?: number | undefined;
509
516
  } | undefined;
510
- isFeatured?: boolean | undefined;
511
- emiEnabled?: boolean | undefined;
512
- website?: string | undefined;
517
+ storeCategory?: string | undefined;
518
+ storeDescription?: string | undefined;
519
+ storeLogoURL?: string | undefined;
520
+ storeBannerURL?: string | undefined;
513
521
  shippingConfig?: {
514
522
  providers: {
515
523
  type: "custom" | "self-courier" | "store-pickup";
@@ -529,17 +537,9 @@ export declare const storeFirestoreSchema: z.ZodObject<{
529
537
  }[];
530
538
  defaultProviderId: string;
531
539
  } | undefined;
532
- storeCategory?: string | undefined;
533
- storeDescription?: string | undefined;
534
- storeLogoURL?: string | undefined;
535
- storeBannerURL?: string | undefined;
536
540
  bio?: string | undefined;
537
- socialLinks?: {
538
- instagram?: string | undefined;
539
- facebook?: string | undefined;
540
- twitter?: string | undefined;
541
- linkedin?: string | undefined;
542
- } | undefined;
541
+ website?: string | undefined;
542
+ emiEnabled?: boolean | undefined;
543
543
  shippingPolicy?: string | undefined;
544
544
  isVacationMode?: boolean | undefined;
545
545
  vacationMessage?: string | undefined;
@@ -609,8 +609,8 @@ export declare const storeListItemSchema: z.ZodObject<{
609
609
  id: string;
610
610
  storeName: string;
611
611
  isPublic: boolean;
612
- storeSlug: string;
613
612
  ownerId: string;
613
+ storeSlug: string;
614
614
  createdAt?: string | undefined;
615
615
  itemsSold?: number | undefined;
616
616
  storeCategory?: string | undefined;
@@ -625,8 +625,8 @@ export declare const storeListItemSchema: z.ZodObject<{
625
625
  id: string;
626
626
  storeName: string;
627
627
  isPublic: boolean;
628
- storeSlug: string;
629
628
  ownerId: string;
629
+ storeSlug: string;
630
630
  createdAt?: string | undefined;
631
631
  itemsSold?: number | undefined;
632
632
  storeCategory?: string | undefined;
@@ -158,7 +158,7 @@ export declare const supportTicketFirestoreSchema: z.ZodObject<{
158
158
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
159
159
  }, z.ZodTypeAny, "passthrough">;
160
160
  userId: string;
161
- category: "account" | "general" | "order_issue" | "billing_payment" | "listing_dispute" | "scam_report" | "refund_request" | "auction_dispute" | "store_change_request" | "order_modification_request" | "unban_request";
161
+ category: "general" | "account" | "order_issue" | "billing_payment" | "listing_dispute" | "scam_report" | "refund_request" | "auction_dispute" | "store_change_request" | "order_modification_request" | "unban_request";
162
162
  description: string;
163
163
  priority: "normal" | "high" | "low" | "urgent";
164
164
  messages: {
@@ -201,7 +201,7 @@ export declare const supportTicketFirestoreSchema: z.ZodObject<{
201
201
  toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
202
202
  }, z.ZodTypeAny, "passthrough">;
203
203
  userId: string;
204
- category: "account" | "general" | "order_issue" | "billing_payment" | "listing_dispute" | "scam_report" | "refund_request" | "auction_dispute" | "store_change_request" | "order_modification_request" | "unban_request";
204
+ category: "general" | "account" | "order_issue" | "billing_payment" | "listing_dispute" | "scam_report" | "refund_request" | "auction_dispute" | "store_change_request" | "order_modification_request" | "unban_request";
205
205
  description: string;
206
206
  priority: "normal" | "high" | "low" | "urgent";
207
207
  messages: {
@@ -100,6 +100,16 @@ const rawTesterChecklistItems = [
100
100
  { key: "search", label: "Search returns relevant results", href: "/search" },
101
101
  { key: "filters", label: "Search/listing filters (price, brand, condition) work correctly" },
102
102
  { key: "pagination", label: "Pagination / infinite scroll works on listing pages" },
103
+ {
104
+ key: "compare-custom-fields",
105
+ label: "Selecting 2+ items and using the \"Compare\" bulk action shows each item's custom spec fields (dimensions, material, edition, etc.) as extra comparison rows, not just image/price/condition/brand/category/store",
106
+ href: "/products",
107
+ },
108
+ {
109
+ key: "compare-double-row-arrows",
110
+ label: "On a homepage section rendered as a double row (e.g. Auctions), the left/right scroll arrows are tall slivers spanning the full row height, not small circular buttons",
111
+ href: "/",
112
+ },
103
113
  {
104
114
  key: "default-listing-not-empty",
105
115
  label: "Products, Auctions, Pre-Orders, Art & Stickers, and Prize Draws listing pages show real items by default — not an empty \"no products found\" state or a toast about a missing Firestore index",
@@ -183,6 +193,11 @@ const rawTesterChecklistItems = [
183
193
  { key: "payment-auto-approve-dispute", label: "An auto-approved order (2h, no admin review) shows the badge, and \"Raise a dispute\" submits successfully" },
184
194
  { key: "checkout-mobile-responsive", label: "The full checkout flow (cart → address → payment → confirmation) is usable and correctly laid out on a mobile viewport" },
185
195
  { key: "checkout-back-navigation", label: "Using the browser back button mid-checkout does not lose cart state or double-submit the order" },
196
+ {
197
+ key: "checkout-manual-payment-consent",
198
+ label: "Choosing manual payment (UPI/Cash) at checkout shows a how-it-works guide (payment steps, refund summary, what happens if an item sells out) and requires a consent checkbox before the \"Pay via UPI / Cash\" button becomes clickable",
199
+ href: "/checkout",
200
+ },
186
201
  ],
187
202
  },
188
203
  {
@@ -235,6 +250,11 @@ const rawTesterChecklistItems = [
235
250
  { key: "wishlist-sold-out-item", label: "A wishlist item whose product later sells out or is removed still displays gracefully (no crash) with an appropriate indicator" },
236
251
  { key: "wishlist-empty-state", label: "The empty-wishlist state renders correctly with no items", href: "/wishlist" },
237
252
  { key: "wishlist-add-to-cart-from-list", label: "Adding a wishlist item directly to the cart from the wishlist page works" },
253
+ { key: "wishlist-card-clickable", label: "Tapping/clicking a wishlist card (not the heart icon) navigates to that product's detail page", href: "/wishlist" },
254
+ { key: "wishlist-heart-solid-red", label: "The wishlist heart icon on a saved item renders as a clearly visible solid red heart, not a washed-out white-on-pale circle", href: "/wishlist" },
255
+ { key: "wishlist-view-remove-buttons", label: "Each wishlist card shows explicit \"View\" and \"Remove\" buttons below it, in addition to the heart toggle", href: "/wishlist" },
256
+ { key: "wishlist-sync-item", label: "Tapping the per-card \"Sync\" button on a wishlist item refreshes its stored price/title/image and removes it if the product is no longer available", href: "/wishlist" },
257
+ { key: "wishlist-sync-all", label: "The \"Sync all\" button in the wishlist header syncs every item and shows a toast summarizing how many were synced/removed", href: "/wishlist" },
238
258
  { key: "view-history", label: "Recently viewed history shows accurate items in most-recent-first order", href: "/user/history" },
239
259
  { key: "history-revisit-reorders", label: "Re-visiting a product already in history removes the old entry and moves it to the front, rather than duplicating it" },
240
260
  { key: "history-fifo-cap", label: "History silently evicts the oldest entry once more than 50 items have been viewed (no error shown to the user)" },
@@ -254,6 +274,16 @@ const rawTesterChecklistItems = [
254
274
  { key: "cart-guest-to-login-merge", label: "A guest cart's items merge correctly into the account's cart after logging in" },
255
275
  { key: "cart-price-revalidated", label: "If a product's price changes after it was added to the cart, checkout uses the current price and shows the buyer the updated total" },
256
276
  { key: "cart-checkout-button-visible", label: "The \"Proceed to Checkout\" button renders as a clearly visible, prominently-colored primary button — not a dull/near-invisible one blending into the page background", href: "/cart" },
277
+ {
278
+ key: "cart-added-toast-totals",
279
+ label: "Adding any item to the cart shows a toast naming the item plus the cart's updated item count and total value (not a bare \"Added to cart\")",
280
+ href: "/products",
281
+ },
282
+ {
283
+ key: "bottom-nav-cart-not-wishlist",
284
+ label: "The mobile bottom navigation bar shows a Cart tab with a live item-count badge; Wishlist is no longer a bottom-tab slot but is still reachable from the header",
285
+ description: "Wishlist was intentionally removed only from the bottom tab bar, not from the header/app-bar or main navigation — confirm the header wishlist icon is unaffected.",
286
+ },
257
287
  ],
258
288
  },
259
289
  {
@@ -477,13 +507,38 @@ const rawTesterChecklistItems = [
477
507
  href: "/events",
478
508
  },
479
509
  { key: "poll-vote-inline", label: "Voting in a poll event from the Overview tab works, shows a confirmation, and a repeat visit shows the already-voted state" },
510
+ {
511
+ key: "poll-leaderboard-shows-tally",
512
+ label: "A poll event's Leaderboard tab shows option labels with vote counts/percentages, not a list of voters ranked by who voted first",
513
+ href: "/events",
514
+ },
515
+ {
516
+ key: "admin-event-entries-export",
517
+ label: "On an event's admin entries page, admin can view poll/form responses inline and download a Markdown report of all entries via the \"Download Report\" button",
518
+ href: "/admin/events",
519
+ },
480
520
  { key: "survey-feedback-submit", label: "Submitting a survey or feedback event's Participate form works, enforces required fields, and shows a success confirmation" },
481
521
  { key: "offer-coupon-display-copy", label: "An offer event shows its coupon code prominently on the Overview tab, and the \"Copy code\" button copies it to the clipboard with visible confirmation" },
482
522
  { key: "raffle-entry", label: "Entering an open_raffle event works and the Participate tab shows the prize hero, eligibility copy, and optional message field (not a blank form)" },
483
523
  { key: "raffle-entry-top-n-scorers", label: "Entering a top_n_scorers raffle event works and the leaderboard reflects entries" },
484
524
  { key: "raffle-entry-top-n-participants", label: "Entering a top_n_participants raffle event works" },
485
- { key: "spin-wheel", label: "Spinning the spin-wheel event works and shows the prize immediately (realtime)" },
525
+ {
526
+ key: "spin-wheel",
527
+ label: "Spinning the spin-wheel event works on the very first attempt and shows the prize immediately (realtime) — no \"Spin failed\" error",
528
+ description: "Previously the first spin always failed because no eventEntries doc existed yet for the user; the spin now finds-or-creates its own entry transactionally.",
529
+ },
530
+ { key: "spin-wheel-max-per-user", label: "Spinning again after using up the event's configured spinMaxPerUser is blocked with a clear message, not silently allowed" },
486
531
  { key: "spin-wheel-window-blocked", label: "A second spin attempt within the same spinWindow is blocked with a clear message" },
532
+ {
533
+ key: "spin-results-tab",
534
+ label: "A spin_wheel event shows a \"Last 10 Spin Results\" tab listing recent winners (or \"Guest\" for anonymous spins) and their prizes",
535
+ href: "/events",
536
+ },
537
+ {
538
+ key: "event-guest-participation-toggle",
539
+ label: "An event created with \"allow guest participation\" enabled accepts one anonymous entry per device/IP and blocks a second attempt from the same device; an event with the toggle off still requires login",
540
+ href: "/admin/events",
541
+ },
487
542
  { key: "leaderboard-live-refresh", label: "After voting/entering an event, navigating to its Leaderboard tab shows the updated standings immediately rather than a stale cached ranking" },
488
543
  ],
489
544
  },
@@ -587,6 +642,16 @@ const rawTesterChecklistItems = [
587
642
  { key: "sections-social-proof-render", label: "Verified stores, tournaments & events, and collector reviews sections render correctly" },
588
643
  { key: "sections-social-feed-hidden", label: "The social-feed section type is correctly hidden on the homepage since it's disabled in Site Settings" },
589
644
  { key: "hero-welcome-logo-sized-padded", label: "The homepage welcome hero's brand mark/logo panel (desktop, right side) is appropriately sized and padded inside its card — not oversized, cramped, or touching/overflowing the card edges", href: "/" },
645
+ {
646
+ key: "welcome-hero-no-gap",
647
+ label: "There is no large empty gap between the sticky header/navbar (or the expanded search bar) and the homepage Welcome hero section below it",
648
+ href: "/",
649
+ },
650
+ {
651
+ key: "promo-banner-overlay",
652
+ label: "The promotion/announcement banner overlays the top of the first homepage section (translucent strip) instead of pushing the page content down with extra vertical space",
653
+ href: "/",
654
+ },
590
655
  ],
591
656
  },
592
657
  ]),
@@ -596,6 +661,8 @@ const rawTesterChecklistItems = [
596
661
  pageLabel: "Homepage & Core Listing Pages",
597
662
  cases: [
598
663
  { key: "homepage-loads", label: "The homepage loads without errors on both desktop and mobile", href: "/" },
664
+ { key: "about-us-in-main-nav", label: "\"About Us\" appears as an item in the main public top navigation, not just the footer", href: "/about" },
665
+ { key: "developer-page-loads", label: "The Developer page loads correctly and is linked from the footer's Support column next to About Us", href: "/developer" },
599
666
  { key: "products-listing-page", label: "The products listing page loads and paginates correctly", href: "/products" },
600
667
  { key: "auctions-listing-page", label: "The auctions listing page loads correctly", href: "/auctions" },
601
668
  { key: "preorders-listing-page", label: "The pre-orders listing page loads correctly", href: "/pre-orders" },
@@ -0,0 +1,14 @@
1
+ import type { PaymentProofReviewMessageInput } from "../types";
2
+ /**
3
+ * Tier PP — message for the payment-proof fast-review WhatsApp push (sent
4
+ * to every `whatsappAdminNotifyNumbers` number when a buyer uploads proof)
5
+ * and for the buyer/seller "share for review" wa.me link (same message,
6
+ * routed through `buildGroupShareLink` instead of the Cloud API push).
7
+ *
8
+ * Pure string builder — deliberately kept in its own file, isolated from
9
+ * `./whatsapp.ts` (which has a top-level `import { createHmac } from
10
+ * "crypto"`), so it can be safely exported from the client-safe barrel.
11
+ * The buyer/seller share-link caller (order payment page) needs this
12
+ * client-side; the crypto-importing sibling functions never can be.
13
+ */
14
+ export declare function buildPaymentProofReviewMessage(input: PaymentProofReviewMessageInput): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tier PP — message for the payment-proof fast-review WhatsApp push (sent
3
+ * to every `whatsappAdminNotifyNumbers` number when a buyer uploads proof)
4
+ * and for the buyer/seller "share for review" wa.me link (same message,
5
+ * routed through `buildGroupShareLink` instead of the Cloud API push).
6
+ *
7
+ * Pure string builder — deliberately kept in its own file, isolated from
8
+ * `./whatsapp.ts` (which has a top-level `import { createHmac } from
9
+ * "crypto"`), so it can be safely exported from the client-safe barrel.
10
+ * The buyer/seller share-link caller (order payment page) needs this
11
+ * client-side; the crypto-importing sibling functions never can be.
12
+ */
13
+ export function buildPaymentProofReviewMessage(input) {
14
+ const { orderId, buyerName, productTitle, totalAmount, reviewUrl } = input;
15
+ const amount = totalAmount.toLocaleString("en-IN");
16
+ return `💳 Payment proof submitted! ${buyerName} uploaded proof for "${productTitle}" (₹${amount}). Order #${orderId}. Please review within 2 hours or it auto-confirms: ${reviewUrl}`;
17
+ }
@@ -1,4 +1,4 @@
1
- import type { CheckoutMessageInput, StatusNotificationInput, WebhookVerifyInput, IncomingWebhookPayload, SendWhatsAppInput, StatusMessageInput, WaBusinessSendInput, WaBusinessTemplateSendInput, CatalogSyncInput, CatalogSyncResult, PurchaseAnnouncementInput, PaymentProofReviewMessageInput } from "../types";
1
+ import type { CheckoutMessageInput, StatusNotificationInput, WebhookVerifyInput, IncomingWebhookPayload, SendWhatsAppInput, StatusMessageInput, WaBusinessSendInput, WaBusinessTemplateSendInput, CatalogSyncInput, CatalogSyncResult, PurchaseAnnouncementInput } from "../types";
2
2
  export declare function buildCheckoutMessageURL(input: CheckoutMessageInput): string;
3
3
  export declare function buildStatusNotificationURL(input: StatusNotificationInput): string;
4
4
  export declare function verifyWebhookSignature(input: WebhookVerifyInput): boolean;
@@ -44,13 +44,7 @@ export declare function buildPurchaseAnnouncementMessage(input: PurchaseAnnounce
44
44
  * This is the only API-compliant way to target a WhatsApp group.
45
45
  */
46
46
  export declare function buildGroupShareLink(message: string): string;
47
- /**
48
- * Tier PP — message for the payment-proof fast-review WhatsApp push (sent
49
- * to every `whatsappAdminNotifyNumbers` number when a buyer uploads proof)
50
- * and for the buyer/seller "share for review" wa.me link (same message,
51
- * routed through `buildGroupShareLink` instead of the Cloud API push).
52
- */
53
- export declare function buildPaymentProofReviewMessage(input: PaymentProofReviewMessageInput): string;
47
+ export { buildPaymentProofReviewMessage } from "./payment-proof-message";
54
48
  /**
55
49
  * Send an outbound WhatsApp message via Twilio REST API.
56
50
  * Returns true on success, false on failure.
@@ -252,17 +252,10 @@ export function buildPurchaseAnnouncementMessage(input) {
252
252
  export function buildGroupShareLink(message) {
253
253
  return `https://wa.me/?text=${encodeURIComponent(message)}`;
254
254
  }
255
- /**
256
- * Tier PP message for the payment-proof fast-review WhatsApp push (sent
257
- * to every `whatsappAdminNotifyNumbers` number when a buyer uploads proof)
258
- * and for the buyer/seller "share for review" wa.me link (same message,
259
- * routed through `buildGroupShareLink` instead of the Cloud API push).
260
- */
261
- export function buildPaymentProofReviewMessage(input) {
262
- const { orderId, buyerName, productTitle, totalAmount, reviewUrl } = input;
263
- const amount = totalAmount.toLocaleString("en-IN");
264
- return `💳 Payment proof submitted! ${buyerName} uploaded proof for "${productTitle}" (₹${amount}). Order #${orderId}. Please review within 2 hours or it auto-confirms: ${reviewUrl}`;
265
- }
255
+ // buildPaymentProofReviewMessage moved to ./payment-proof-message.ts (pure,
256
+ // no crypto import) so it can be exported client-safe. Re-exported here for
257
+ // backward compatibility with existing server-side importers of this file.
258
+ export { buildPaymentProofReviewMessage } from "./payment-proof-message";
266
259
  /**
267
260
  * Send an outbound WhatsApp message via Twilio REST API.
268
261
  * Returns true on success, false on failure.
@@ -48,6 +48,17 @@ export declare class UserWishlistRepository {
48
48
  productSnapshot?: WishlistItemSnapshot;
49
49
  }): Promise<number>;
50
50
  removeItem(userSlug: string, productId: string): Promise<void>;
51
+ /**
52
+ * Overwrites the stored `productSnapshot` (title/thumb/currentPrice) for
53
+ * one or more surviving items in place — used by the "sync" feature to
54
+ * refresh what's persisted on the wishlist doc against the live product,
55
+ * distinct from `getWishlistItems`'s existing behaviour of just joining in
56
+ * live product data for *display* without ever writing it back.
57
+ */
58
+ syncSnapshots(userSlug: string, updates: {
59
+ productId: string;
60
+ snapshot: WishlistItemSnapshot;
61
+ }[]): Promise<void>;
51
62
  clearWishlist(userSlug: string): Promise<void>;
52
63
  /** Admin: returns one row per user (for the admin insights view). */
53
64
  findAllSummaries(): Promise<{
@@ -170,6 +170,39 @@ export class UserWishlistRepository {
170
170
  throw error;
171
171
  }
172
172
  }
173
+ /**
174
+ * Overwrites the stored `productSnapshot` (title/thumb/currentPrice) for
175
+ * one or more surviving items in place — used by the "sync" feature to
176
+ * refresh what's persisted on the wishlist doc against the live product,
177
+ * distinct from `getWishlistItems`'s existing behaviour of just joining in
178
+ * live product data for *display* without ever writing it back.
179
+ */
180
+ async syncSnapshots(userSlug, updates) {
181
+ if (updates.length === 0)
182
+ return;
183
+ const db = getAdminDb();
184
+ const ref = this.docRef(userSlug);
185
+ const byId = new Map(updates.map((u) => [u.productId, u.snapshot]));
186
+ try {
187
+ await db.runTransaction(async (tx) => {
188
+ const snap = await tx.get(ref);
189
+ if (!snap.exists)
190
+ return;
191
+ const items = normaliseItems(snap.data()?.items);
192
+ const next = items.map((item) => byId.has(item.productId)
193
+ ? { ...item, productSnapshot: byId.get(item.productId) }
194
+ : item);
195
+ tx.set(ref, { userId: userSlug, items: next, updatedAt: new Date() });
196
+ });
197
+ }
198
+ catch (error) {
199
+ serverLogger.error("UserWishlistRepository.syncSnapshots error", {
200
+ userSlug,
201
+ error,
202
+ });
203
+ throw error;
204
+ }
205
+ }
173
206
  async clearWishlist(userSlug) {
174
207
  try {
175
208
  await this.docRef(userSlug).set({
package/dist/index.d.ts CHANGED
@@ -910,6 +910,8 @@ export { HowOrdersWorkView } from "./features/about/index";
910
910
  export { HowPayoutsWorkView } from "./features/about/index";
911
911
  export { HowPreOrdersWorkView } from "./features/about/index";
912
912
  export { HowReviewsWorkView } from "./features/about/index";
913
+ export { PolicyPageView } from "./features/about/index";
914
+ export { DeveloperView } from "./features/about/index";
913
915
  export { PublicProfileView } from "./features/about/index";
914
916
  export { SecurityPrivacyView } from "./features/about/index";
915
917
  export { ShippingPolicyView } from "./features/about/index";
@@ -932,6 +934,7 @@ export type { HowPayoutsWorkViewProps } from "./features/about/index";
932
934
  export type { HowPreOrdersWorkViewProps } from "./features/about/index";
933
935
  export type { HowReviewsWorkViewProps } from "./features/about/index";
934
936
  export type { PolicyPageViewProps } from "./features/about/index";
937
+ export type { DeveloperViewProps } from "./features/about/index";
935
938
  export type { PublicProfileViewProps } from "./features/about/index";
936
939
  export type { SecurityPrivacyViewProps } from "./features/about/index";
937
940
  export type { ShippingPolicyViewProps } from "./features/about/index";
@@ -1393,6 +1396,7 @@ export { placeBid, buyNowAuction } from "./features/auctions/server";
1393
1396
  export type { PlaceBidInput, BuyNowAuctionInput, BuyNowAuctionResult } from "./features/auctions/server";
1394
1397
  export type { PlaceBidResult } from "./features/auctions/server";
1395
1398
  export { CHECKOUT_VALUE_OTP_VERIFY_RATE_LIMIT } from "./features/auth/checkout-value-otp";
1399
+ export { sendCheckoutValueOtp, verifyCheckoutValueOtp, } from "./features/checkout/server";
1396
1400
  export { authMeGET } from "./features/auth/server";
1397
1401
  export { createPasswordResetToken } from "./features/auth/server";
1398
1402
  export { createVerificationToken } from "./features/auth/server";
@@ -1659,11 +1663,6 @@ export { listBrandCategories } from "./features/categories/server";
1659
1663
  export { listCategories } from "./features/categories/server";
1660
1664
  export { listTopLevelCategories } from "./features/categories/server";
1661
1665
  export { updateCategory } from "./features/categories/server";
1662
- export { FailedCheckoutRepository } from "./features/checkout/server";
1663
- export { failedCheckoutRepository } from "./features/checkout/server";
1664
- export { sendCheckoutValueOtp, verifyCheckoutValueOtp, isCheckoutValueOtpVerified, } from "./features/checkout/server";
1665
- export type { FailedCheckoutMeta } from "./features/checkout/server";
1666
- export type { FailedPaymentMeta } from "./features/checkout/server";
1667
1666
  export { FAILED_CHECKOUTS_COLLECTION } from "./features/checkout/schemas/index";
1668
1667
  export { FAILED_PAYMENTS_COLLECTION } from "./features/checkout/schemas/index";
1669
1668
  export type { FailedCheckoutDocument } from "./features/checkout/schemas/index";
@@ -1703,13 +1702,6 @@ export type { ContactFormProps } from "./features/contact/index";
1703
1702
  export type { ContactInfoItem } from "./features/contact/index";
1704
1703
  export type { ContactInfoSidebarProps } from "./features/contact/index";
1705
1704
  export type { UseContactSubmitOptions } from "./features/contact/index";
1706
- export { sendContactEmail } from "./features/contact/server";
1707
- export { sendEmail } from "./features/contact/server";
1708
- export { sendOrderConfirmationEmail } from "./features/contact/server";
1709
- export { sendPasswordResetEmailWithLink } from "./features/contact/server";
1710
- export { sendSiteSettingsChangedEmail } from "./features/contact/server";
1711
- export { sendVerificationEmailWithLink } from "./features/contact/server";
1712
- export type { OrderConfirmationEmailParams } from "./features/contact/server";
1713
1705
  export { AdminCopilotView } from "./features/copilot/index";
1714
1706
  export { useCopilotChat } from "./features/copilot/index";
1715
1707
  export { useCopilotFeedback } from "./features/copilot/index";
@@ -1843,6 +1835,7 @@ export type { EventUpdateInput } from "./features/events/index";
1843
1835
  export type { FeedbackConfig } from "./features/events/index";
1844
1836
  export type { FormFieldType } from "./features/events/index";
1845
1837
  export type { LeaderboardEntry } from "./features/events/index";
1838
+ export type { PollResultEntry } from "./features/events/index";
1846
1839
  export type { OfferConfig } from "./features/events/index";
1847
1840
  export type { PollConfig } from "./features/events/index";
1848
1841
  export type { PollResultsVisibility } from "./features/events/index";
@@ -1863,6 +1856,8 @@ export { enterEvent } from "./features/events/server";
1863
1856
  export { eventIdGET } from "./features/events/server";
1864
1857
  export { eventsGET } from "./features/events/server";
1865
1858
  export { getEventLeaderboard } from "./features/events/server";
1859
+ export { getEventPollResults } from "./features/events/server";
1860
+ export { getEventSpinResults } from "./features/events/server";
1866
1861
  export { getBugHunterLeaderboard } from "./features/tester/server";
1867
1862
  export { getPublicEventById } from "./features/events/server";
1868
1863
  export { listPublicEvents } from "./features/events/server";
package/dist/index.js CHANGED
@@ -1875,6 +1875,10 @@ export { HowPreOrdersWorkView } from "./features/about/index";
1875
1875
  export { HowReviewsWorkView } from "./features/about/index";
1876
1876
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
1877
1877
  // PolicyPageView - Component for policy page view.
1878
+ export { PolicyPageView } from "./features/about/index";
1879
+ // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
1880
+ // DeveloperView - Component for developer intro/portfolio view.
1881
+ export { DeveloperView } from "./features/about/index";
1878
1882
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
1879
1883
  // PublicProfileView - Component for public profile view.
1880
1884
  export { PublicProfileView } from "./features/about/index";
@@ -2587,6 +2591,12 @@ export { placeBid, buyNowAuction } from "./features/auctions/server";
2587
2591
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
2588
2592
  // CHECKOUT_VALUE_OTP_VERIFY_RATE_LIMIT - Constant used across modules.
2589
2593
  export { CHECKOUT_VALUE_OTP_VERIFY_RATE_LIMIT } from "./features/auth/checkout-value-otp";
2594
+ // [SERVER-ONLY] Tier PP — high-value checkout OTP gate. "use server" actions
2595
+ // belong in both index.ts and server.ts per the appkit Export Rules table;
2596
+ // these were only in server.ts, leaving src/actions/checkout.actions.ts's
2597
+ // `import { sendCheckoutValueOtp, verifyCheckoutValueOtp } from "@mohasinac/appkit"`
2598
+ // unresolved.
2599
+ export { sendCheckoutValueOtp, verifyCheckoutValueOtp, } from "./features/checkout/server";
2590
2600
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
2591
2601
  // authMeGET - Shared export for auth me get.
2592
2602
  export { authMeGET } from "./features/auth/server";
@@ -3122,15 +3132,6 @@ export { listTopLevelCategories } from "./features/categories/server";
3122
3132
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3123
3133
  // updateCategory - Helper for update category.
3124
3134
  export { updateCategory } from "./features/categories/server";
3125
- // ./features/checkout/server
3126
- // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
3127
- // FailedCheckoutRepository - Shared export for failed checkout repository.
3128
- export { FailedCheckoutRepository } from "./features/checkout/server";
3129
- // [DB]-Database layer â€" uses firebase-admin or another server-side DB SDK; can only run in a trusted server environment.
3130
- // failedCheckoutRepository - Shared export for failed checkout repository.
3131
- export { failedCheckoutRepository } from "./features/checkout/server";
3132
- // [SERVER-ONLY] Tier PP — high-value checkout OTP gate.
3133
- export { sendCheckoutValueOtp, verifyCheckoutValueOtp, isCheckoutValueOtpVerified, } from "./features/checkout/server";
3134
3135
  // ./features/checkout/schemas/index
3135
3136
  // [SCHEMA]-Schema / data-shape constant â€" Zod validator, default-value object, or Firestore collection/field name constant.
3136
3137
  // FAILED_CHECKOUTS_COLLECTION - Constant used across modules.
@@ -3209,25 +3210,6 @@ export { ContactPageView } from "./features/contact/index";
3209
3210
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3210
3211
  // useContactSubmit - React hook for use contact submit.
3211
3212
  export { useContactSubmit } from "./features/contact/index";
3212
- // ./features/contact/server
3213
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3214
- // sendContactEmail - Shared export for send contact email.
3215
- export { sendContactEmail } from "./features/contact/server";
3216
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3217
- // sendEmail - Shared export for send email.
3218
- export { sendEmail } from "./features/contact/server";
3219
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3220
- // sendOrderConfirmationEmail - Shared export for send order confirmation email.
3221
- export { sendOrderConfirmationEmail } from "./features/contact/server";
3222
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3223
- // sendPasswordResetEmailWithLink - Shared export for send password reset email with link.
3224
- export { sendPasswordResetEmailWithLink } from "./features/contact/server";
3225
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3226
- // sendSiteSettingsChangedEmail - Shared export for send site settings changed email.
3227
- export { sendSiteSettingsChangedEmail } from "./features/contact/server";
3228
- // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3229
- // sendVerificationEmailWithLink - Shared export for send verification email with link.
3230
- export { sendVerificationEmailWithLink } from "./features/contact/server";
3231
3213
  // ./features/copilot/index
3232
3214
  // [CLIENT-SSR]-Runs in both SSR and browser â€" React component or hook that does not depend on browser-only APIs.
3233
3215
  // AdminCopilotView - Component for admin copilot view.
@@ -3485,6 +3467,12 @@ export { eventsGET } from "./features/events/server";
3485
3467
  // getEventLeaderboard - Helper for get event leaderboard.
3486
3468
  export { getEventLeaderboard } from "./features/events/server";
3487
3469
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3470
+ // getEventPollResults - Helper for get event poll results (per-option vote tally).
3471
+ export { getEventPollResults } from "./features/events/server";
3472
+ // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3473
+ // getEventSpinResults - Last N winning spins for a spin_wheel event, most recent first.
3474
+ export { getEventSpinResults } from "./features/events/server";
3475
+ // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
3488
3476
  // getBugHunterLeaderboard - Ranks testers by confirmed-bug count.
3489
3477
  export { getBugHunterLeaderboard } from "./features/tester/server";
3490
3478
  // [SERVER-ONLY]-Server-only â€" uses Node.js, Next.js server internals, or third-party server SDKs (auth, email, payment, shipping).
@@ -19,7 +19,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
19
  import { useEffect } from "react";
20
20
  import { Heading, Text } from "../../ui/components/Typography";
21
21
  import { Button } from "../../ui/components/Button";
22
- import { Stack } from "@mohasinac/appkit";
22
+ import { Stack } from "@mohasinac/appkit/client";
23
23
  import { trackError, ErrorCategory, ErrorSeverity, } from "../../monitoring/error-tracking";
24
24
  export function ErrorView({ error, reset, heading = "Something went wrong", description = "An unexpected error occurred. Please try again.", retryLabel = "Try again", }) {
25
25
  useEffect(() => {
@@ -20,7 +20,7 @@ import { Heading, Text } from "../../ui/components/Typography";
20
20
  import { TextLink } from "../../ui/components/TextLink";
21
21
  import { SiteMark } from "../../ui/components/SiteMark";
22
22
  import { DEFAULT_ROUTE_MAP } from "../routing/route-map";
23
- import { Stack } from "@mohasinac/appkit";
23
+ import { Stack } from "@mohasinac/appkit/client";
24
24
  export function NotFoundView({ heading = "404 — Page not found", description = "The page you are looking for does not exist.", homeLabel = "Go home", homeHref = DEFAULT_ROUTE_MAP.HOME, }) {
25
25
  return (_jsxs(Stack, { justify: "center", className: "min-h-[60vh] text-center", padding: "x-xl", align: "center", children: [_jsx(SiteMark, { size: "xl" }), _jsx(Heading, { level: 1, variant: "primary", size: "7xl", className: "mb-2", weight: "bold", children: "404" }), _jsx(Heading, { level: 2, className: "mb-3", children: heading }), _jsx(Text, { variant: "secondary", className: "mb-8", children: description }), _jsx(TextLink, { href: homeHref, children: homeLabel })] }));
26
26
  }
@@ -16,7 +16,7 @@ import { Row } from "../../ui/components/Layout";
16
16
  import { Heading, Text } from "../../ui/components/Typography";
17
17
  import { TextLink } from "../../ui/components/TextLink";
18
18
  import { DEFAULT_ROUTE_MAP } from "../routing/route-map";
19
- import { Stack } from "@mohasinac/appkit";
19
+ import { Stack } from "@mohasinac/appkit/client";
20
20
  export function UnauthorizedView({ heading = "401 — Unauthorized", description = "You need to be signed in to view this page.", loginLabel = "Sign in", loginHref = DEFAULT_ROUTE_MAP.AUTH.LOGIN, homeLabel = "Go home", homeHref = DEFAULT_ROUTE_MAP.HOME, }) {
21
21
  return (_jsxs(Stack, { justify: "center", className: "min-h-[60vh] text-center", padding: "x-xl", align: "center", children: [_jsx(Heading, { level: 1, variant: "primary", size: "7xl", className: "mb-2", weight: "bold", children: "401" }), _jsx(Heading, { level: 2, className: "mb-3", children: heading }), _jsx(Text, { variant: "secondary", className: "mb-8", children: description }), _jsxs(Row, { gap: "md", children: [_jsx(TextLink, { href: loginHref, children: loginLabel }), _jsx(TextLink, { href: homeHref, children: homeLabel })] })] }));
22
22
  }