@mohasinac/appkit 2.7.10 → 2.7.12

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 (148) hide show
  1. package/dist/_internal/server/jobs/core/assignSpinPrize.js +8 -7
  2. package/dist/_internal/server/jobs/core/bundleStockSync.js +11 -6
  3. package/dist/_internal/server/jobs/core/countersReconcile.js +3 -2
  4. package/dist/_internal/server/jobs/core/onProductStockChange.js +12 -7
  5. package/dist/_internal/server/jobs/core/onProductWrite.js +3 -2
  6. package/dist/_internal/server/jobs/core/prizeRevealClose.js +7 -5
  7. package/dist/_internal/server/jobs/core/prizeRevealExpiry.js +11 -6
  8. package/dist/_internal/server/jobs/core/prizeRevealOpen.js +13 -7
  9. package/dist/_internal/server/jobs/core/prizeRevealReminder.js +9 -4
  10. package/dist/_internal/server/jobs/core/triggerEventRaffle.js +3 -2
  11. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  12. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
  13. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  14. package/dist/_internal/shared/features/products/schema.d.ts +20 -20
  15. package/dist/_internal/shared/features/promotions/schema.d.ts +2 -2
  16. package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
  17. package/dist/configs/next.js +17 -1
  18. package/dist/constants/field-names.d.ts +813 -0
  19. package/dist/constants/field-names.js +918 -0
  20. package/dist/constants/sort.d.ts +7 -0
  21. package/dist/constants/sort.js +5 -0
  22. package/dist/constants/table-keys.d.ts +48 -0
  23. package/dist/constants/table-keys.js +46 -0
  24. package/dist/features/account/components/AddressesIndexListing.js +9 -6
  25. package/dist/features/admin/components/AdminAllEventEntriesView.js +4 -1
  26. package/dist/features/admin/components/AdminBidsView.js +4 -1
  27. package/dist/features/admin/components/AdminBlogView.js +9 -2
  28. package/dist/features/admin/components/AdminBrandsView.js +9 -2
  29. package/dist/features/admin/components/AdminCarouselView.js +4 -1
  30. package/dist/features/admin/components/AdminCartsView.js +4 -1
  31. package/dist/features/admin/components/AdminCategoriesView.js +9 -2
  32. package/dist/features/admin/components/AdminContactView.js +4 -1
  33. package/dist/features/admin/components/AdminCouponsView.js +4 -1
  34. package/dist/features/admin/components/AdminFaqsView.js +5 -1
  35. package/dist/features/admin/components/AdminFeaturesView.js +5 -2
  36. package/dist/features/admin/components/AdminHistoryView.js +5 -1
  37. package/dist/features/admin/components/AdminNewsletterView.js +4 -1
  38. package/dist/features/admin/components/AdminNotificationsView.js +4 -1
  39. package/dist/features/admin/components/AdminOrdersView.js +14 -12
  40. package/dist/features/admin/components/AdminPayoutsView.js +4 -1
  41. package/dist/features/admin/components/AdminPrizeDrawsView.js +4 -1
  42. package/dist/features/admin/components/AdminProductsView.js +14 -3
  43. package/dist/features/admin/components/AdminReturnRequestsView.js +4 -1
  44. package/dist/features/admin/components/AdminReviewsView.js +4 -1
  45. package/dist/features/admin/components/AdminScammersView.js +4 -1
  46. package/dist/features/admin/components/AdminSessionsView.js +4 -1
  47. package/dist/features/admin/components/AdminStoreAddressesView.js +5 -1
  48. package/dist/features/admin/components/AdminStoresView.js +10 -3
  49. package/dist/features/admin/components/AdminSublistingCategoriesView.js +4 -1
  50. package/dist/features/admin/components/AdminSupportTicketsView.js +4 -1
  51. package/dist/features/admin/components/AdminTeamView.js +4 -1
  52. package/dist/features/admin/components/AdminUsersView.js +9 -12
  53. package/dist/features/admin/components/AdminViewCards.d.ts +12 -0
  54. package/dist/features/admin/components/AdminViewCards.js +53 -0
  55. package/dist/features/admin/components/AdminWishlistsView.js +4 -1
  56. package/dist/features/auctions/repository/bid.repository.js +1 -6
  57. package/dist/features/auctions/schemas/index.d.ts +4 -4
  58. package/dist/features/blog/actions/blog-actions.d.ts +16 -16
  59. package/dist/features/blog/components/BlogFilters.d.ts +28 -28
  60. package/dist/features/blog/components/BlogFilters.js +18 -15
  61. package/dist/features/blog/components/BlogIndexListing.js +24 -13
  62. package/dist/features/blog/schemas/index.d.ts +10 -10
  63. package/dist/features/categories/components/CategoriesIndexListing.js +30 -19
  64. package/dist/features/categories/schemas/index.d.ts +2 -2
  65. package/dist/features/events/components/AdminEventsView.js +5 -1
  66. package/dist/features/events/components/EventFilters.d.ts +24 -24
  67. package/dist/features/events/components/EventFilters.js +16 -13
  68. package/dist/features/events/components/EventStatusBadge.js +1 -0
  69. package/dist/features/events/components/EventsIndexListing.js +36 -24
  70. package/dist/features/events/components/EventsListPageView.js +13 -10
  71. package/dist/features/events/schemas/firestore.d.ts +1 -0
  72. package/dist/features/events/schemas/firestore.js +1 -0
  73. package/dist/features/events/schemas/index.d.ts +1 -1
  74. package/dist/features/events/types/index.d.ts +1 -1
  75. package/dist/features/faq/actions/faq-actions.d.ts +10 -10
  76. package/dist/features/faq/schemas/index.d.ts +4 -4
  77. package/dist/features/layout/TitleBarLayout.js +1 -1
  78. package/dist/features/orders/components/OrderFilters.d.ts +20 -20
  79. package/dist/features/orders/components/OrderFilters.js +33 -30
  80. package/dist/features/orders/repository/orders.repository.js +1 -15
  81. package/dist/features/orders/schemas/index.d.ts +2 -2
  82. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +44 -36
  83. package/dist/features/pre-orders/schemas/index.d.ts +3 -3
  84. package/dist/features/products/components/AuctionsIndexListing.js +63 -30
  85. package/dist/features/products/components/BidHistory.d.ts +0 -1
  86. package/dist/features/products/components/BidHistory.js +1 -1
  87. package/dist/features/products/components/PrizeDrawsIndexListing.js +44 -37
  88. package/dist/features/products/components/ProductDetailPageView.js +1 -1
  89. package/dist/features/products/components/ProductFilters.d.ts +20 -20
  90. package/dist/features/products/components/ProductFilters.js +62 -59
  91. package/dist/features/products/components/ProductsIndexListing.js +37 -29
  92. package/dist/features/products/components/ProductsIndexPageView.js +18 -10
  93. package/dist/features/products/hooks/useProducts.js +2 -0
  94. package/dist/features/products/repository/products.repository.js +2 -22
  95. package/dist/features/products/schemas/index.d.ts +28 -28
  96. package/dist/features/products/schemas/product-features.validators.d.ts +12 -12
  97. package/dist/features/products/types/index.d.ts +2 -0
  98. package/dist/features/promotions/components/CouponsIndexListing.js +21 -17
  99. package/dist/features/promotions/schemas/index.d.ts +4 -4
  100. package/dist/features/reviews/components/ReviewDetailShell.js +6 -5
  101. package/dist/features/reviews/components/ReviewFilters.d.ts +16 -16
  102. package/dist/features/reviews/components/ReviewFilters.js +10 -7
  103. package/dist/features/reviews/components/ReviewsIndexListing.js +25 -14
  104. package/dist/features/reviews/components/ReviewsList.d.ts +5 -2
  105. package/dist/features/reviews/components/ReviewsList.js +11 -5
  106. package/dist/features/reviews/schemas/firestore.d.ts +1 -0
  107. package/dist/features/reviews/schemas/index.d.ts +8 -8
  108. package/dist/features/reviews/types/index.d.ts +1 -0
  109. package/dist/features/search/schemas/index.d.ts +2 -2
  110. package/dist/features/seller/components/SellerAuctionsView.js +5 -1
  111. package/dist/features/seller/components/SellerBidsView.js +4 -1
  112. package/dist/features/seller/components/SellerCouponsView.js +4 -1
  113. package/dist/features/seller/components/SellerOffersView.js +5 -1
  114. package/dist/features/seller/components/SellerOrdersView.js +4 -1
  115. package/dist/features/seller/components/SellerPayoutsView.js +5 -1
  116. package/dist/features/seller/components/SellerPreOrdersView.js +4 -1
  117. package/dist/features/seller/components/SellerPrizeDrawsView.js +4 -1
  118. package/dist/features/seller/components/SellerProductsView.js +4 -1
  119. package/dist/features/seller/schemas/index.d.ts +10 -10
  120. package/dist/features/stores/api/route.js +10 -1
  121. package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
  122. package/dist/features/stores/components/StorePreOrdersListing.js +2 -1
  123. package/dist/features/stores/components/StoreReviewsListing.js +1 -1
  124. package/dist/features/stores/components/StoresIndexListing.js +45 -27
  125. package/dist/features/stores/schemas/firestore.d.ts +1 -0
  126. package/dist/features/stores/schemas/index.d.ts +4 -4
  127. package/dist/index.d.ts +8 -1
  128. package/dist/index.js +12 -1
  129. package/dist/react/hooks/useUrlTable.js +2 -1
  130. package/dist/seed/bids-seed-data.js +45 -44
  131. package/dist/seed/categories-seed-data.js +41 -40
  132. package/dist/seed/coupons-seed-data.js +41 -40
  133. package/dist/seed/products-auctions-seed-data.js +54 -53
  134. package/dist/seed/products-preorders-seed-data.js +25 -24
  135. package/dist/seed/products-prize-draws-seed-data.js +24 -23
  136. package/dist/seed/products-standard-seed-data.js +294 -293
  137. package/dist/seed/reviews-seed-data.js +61 -60
  138. package/dist/seed/scammers-seed-data.js +3 -2
  139. package/dist/seed/stores-seed-data.js +9 -8
  140. package/dist/seed/support-tickets-seed-data.js +13 -12
  141. package/dist/seed/users-seed-data.js +28 -27
  142. package/dist/tailwind-utilities.css +1 -1
  143. package/dist/ui/components/ListingToolbar.d.ts +7 -4
  144. package/dist/ui/components/ListingToolbar.js +4 -3
  145. package/dist/ui/components/SiteLogo.js +1 -1
  146. package/dist/utils/sieve-builder.d.ts +41 -0
  147. package/dist/utils/sieve-builder.js +66 -0
  148. package/package.json +1 -1
@@ -117,8 +117,8 @@ export declare const productItemSchema: z.ZodObject<{
117
117
  isWon: z.ZodBoolean;
118
118
  }, "strip", z.ZodTypeAny, {
119
119
  title: string;
120
- images: string[];
121
120
  condition: string;
121
+ images: string[];
122
122
  itemNumber: number;
123
123
  isWon: boolean;
124
124
  video?: {
@@ -129,8 +129,8 @@ export declare const productItemSchema: z.ZodObject<{
129
129
  estimatedValue?: number | undefined;
130
130
  }, {
131
131
  title: string;
132
- images: string[];
133
132
  condition: string;
133
+ images: string[];
134
134
  itemNumber: number;
135
135
  isWon: boolean;
136
136
  video?: {
@@ -305,19 +305,24 @@ export declare const productItemSchema: z.ZodObject<{
305
305
  youtubeId?: string | undefined;
306
306
  }[] | undefined;
307
307
  category?: string | undefined;
308
- images?: string[] | undefined;
308
+ brand?: string | undefined;
309
+ condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
310
+ tags?: string[] | undefined;
311
+ featured?: boolean | undefined;
312
+ listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
313
+ inStock?: boolean | undefined;
309
314
  rating?: number | undefined;
315
+ preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
316
+ prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
317
+ categorySlug?: string | undefined;
318
+ images?: string[] | undefined;
310
319
  description?: string | undefined;
311
- listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
312
- featured?: boolean | undefined;
313
320
  isPromoted?: boolean | undefined;
314
321
  slug?: string | undefined;
315
322
  subcategory?: string | undefined;
316
- brand?: string | undefined;
317
323
  stockQuantity?: number | undefined;
318
324
  availableQuantity?: number | undefined;
319
325
  mainImage?: string | undefined;
320
- tags?: string[] | undefined;
321
326
  specifications?: {
322
327
  value: string;
323
328
  name: string;
@@ -326,7 +331,6 @@ export declare const productItemSchema: z.ZodObject<{
326
331
  features?: string[] | undefined;
327
332
  shippingInfo?: string | undefined;
328
333
  returnPolicy?: string | undefined;
329
- condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
330
334
  insurance?: boolean | undefined;
331
335
  insuranceCost?: number | undefined;
332
336
  shippingPaidBy?: "seller" | "buyer" | undefined;
@@ -345,7 +349,6 @@ export declare const productItemSchema: z.ZodObject<{
345
349
  preOrderDepositAmount?: number | undefined;
346
350
  preOrderMaxQuantity?: number | undefined;
347
351
  preOrderCurrentCount?: number | undefined;
348
- preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
349
352
  preOrderCancellable?: boolean | undefined;
350
353
  pickupAddressId?: string | undefined;
351
354
  viewCount?: number | undefined;
@@ -381,8 +384,8 @@ export declare const productItemSchema: z.ZodObject<{
381
384
  partOfBundleTitles?: string[] | undefined;
382
385
  prizeDrawItems?: {
383
386
  title: string;
384
- images: string[];
385
387
  condition: string;
388
+ images: string[];
386
389
  itemNumber: number;
387
390
  isWon: boolean;
388
391
  video?: {
@@ -397,13 +400,10 @@ export declare const productItemSchema: z.ZodObject<{
397
400
  prizeCurrentEntries?: number | undefined;
398
401
  prizeRevealWindowStart?: string | Date | undefined;
399
402
  prizeRevealWindowEnd?: string | Date | undefined;
400
- prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
401
403
  prizeRevealDeadlineDays?: number | undefined;
402
404
  prizeGithubFileUrl?: string | undefined;
403
405
  originalPrice?: number | undefined;
404
- categorySlug?: string | undefined;
405
406
  sellerAvatar?: string | undefined;
406
- inStock?: boolean | undefined;
407
407
  stockCount?: number | undefined;
408
408
  attributes?: Record<string, string> | undefined;
409
409
  seo?: {
@@ -434,19 +434,24 @@ export declare const productItemSchema: z.ZodObject<{
434
434
  youtubeId?: string | undefined;
435
435
  }[] | undefined;
436
436
  category?: string | undefined;
437
- images?: string[] | undefined;
437
+ brand?: string | undefined;
438
+ condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
439
+ tags?: string[] | undefined;
440
+ featured?: boolean | undefined;
441
+ listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
442
+ inStock?: boolean | undefined;
438
443
  rating?: number | undefined;
444
+ preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
445
+ prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
446
+ categorySlug?: string | undefined;
447
+ images?: string[] | undefined;
439
448
  description?: string | undefined;
440
- listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
441
- featured?: boolean | undefined;
442
449
  isPromoted?: boolean | undefined;
443
450
  slug?: string | undefined;
444
451
  subcategory?: string | undefined;
445
- brand?: string | undefined;
446
452
  stockQuantity?: number | undefined;
447
453
  availableQuantity?: number | undefined;
448
454
  mainImage?: string | undefined;
449
- tags?: string[] | undefined;
450
455
  specifications?: {
451
456
  value: string;
452
457
  name: string;
@@ -455,7 +460,6 @@ export declare const productItemSchema: z.ZodObject<{
455
460
  features?: string[] | undefined;
456
461
  shippingInfo?: string | undefined;
457
462
  returnPolicy?: string | undefined;
458
- condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
459
463
  insurance?: boolean | undefined;
460
464
  insuranceCost?: number | undefined;
461
465
  shippingPaidBy?: "seller" | "buyer" | undefined;
@@ -474,7 +478,6 @@ export declare const productItemSchema: z.ZodObject<{
474
478
  preOrderDepositAmount?: number | undefined;
475
479
  preOrderMaxQuantity?: number | undefined;
476
480
  preOrderCurrentCount?: number | undefined;
477
- preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
478
481
  preOrderCancellable?: boolean | undefined;
479
482
  pickupAddressId?: string | undefined;
480
483
  viewCount?: number | undefined;
@@ -510,8 +513,8 @@ export declare const productItemSchema: z.ZodObject<{
510
513
  partOfBundleTitles?: string[] | undefined;
511
514
  prizeDrawItems?: {
512
515
  title: string;
513
- images: string[];
514
516
  condition: string;
517
+ images: string[];
515
518
  itemNumber: number;
516
519
  isWon: boolean;
517
520
  video?: {
@@ -526,13 +529,10 @@ export declare const productItemSchema: z.ZodObject<{
526
529
  prizeCurrentEntries?: number | undefined;
527
530
  prizeRevealWindowStart?: string | Date | undefined;
528
531
  prizeRevealWindowEnd?: string | Date | undefined;
529
- prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
530
532
  prizeRevealDeadlineDays?: number | undefined;
531
533
  prizeGithubFileUrl?: string | undefined;
532
534
  originalPrice?: number | undefined;
533
- categorySlug?: string | undefined;
534
535
  sellerAvatar?: string | undefined;
535
- inStock?: boolean | undefined;
536
536
  stockCount?: number | undefined;
537
537
  attributes?: Record<string, string> | undefined;
538
538
  seo?: {
@@ -567,9 +567,9 @@ export declare const productListParamsSchema: z.ZodObject<{
567
567
  category?: string | undefined;
568
568
  minPrice?: number | undefined;
569
569
  maxPrice?: number | undefined;
570
- listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
571
- featured?: boolean | undefined;
572
570
  condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
571
+ featured?: boolean | undefined;
572
+ listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
573
573
  inStock?: boolean | undefined;
574
574
  }, {
575
575
  sort?: string | undefined;
@@ -581,8 +581,8 @@ export declare const productListParamsSchema: z.ZodObject<{
581
581
  category?: string | undefined;
582
582
  minPrice?: number | undefined;
583
583
  maxPrice?: number | undefined;
584
- listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
585
- featured?: boolean | undefined;
586
584
  condition?: "new" | "used" | "refurbished" | "broken" | "like_new" | "good" | "fair" | "poor" | undefined;
585
+ featured?: boolean | undefined;
586
+ listingType?: "auction" | "standard" | "pre-order" | "prize-draw" | "bundle" | undefined;
587
587
  inStock?: boolean | undefined;
588
588
  }>;
@@ -26,9 +26,9 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
26
26
  scope: "store" | "platform";
27
27
  icon: string;
28
28
  isActive: boolean;
29
- category: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform";
30
- productTypes: ("all" | "product" | "auction" | "preorder")[];
29
+ category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
31
30
  displayOrder: number;
31
+ productTypes: ("all" | "product" | "auction" | "preorder")[];
32
32
  storeId?: string | undefined;
33
33
  description?: string | undefined;
34
34
  iconColor?: string | undefined;
@@ -37,9 +37,9 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
37
37
  scope: "store" | "platform";
38
38
  icon: string;
39
39
  isActive: boolean;
40
- category: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform";
41
- productTypes: ("all" | "product" | "auction" | "preorder")[];
40
+ category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
42
41
  displayOrder: number;
42
+ productTypes: ("all" | "product" | "auction" | "preorder")[];
43
43
  storeId?: string | undefined;
44
44
  description?: string | undefined;
45
45
  iconColor?: string | undefined;
@@ -58,18 +58,18 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
58
58
  label: string;
59
59
  icon: string;
60
60
  isActive: boolean;
61
- category: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform";
62
- productTypes: ("all" | "product" | "auction" | "preorder")[];
61
+ category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
63
62
  displayOrder: number;
63
+ productTypes: ("all" | "product" | "auction" | "preorder")[];
64
64
  description?: string | undefined;
65
65
  iconColor?: string | undefined;
66
66
  }, {
67
67
  label: string;
68
68
  icon: string;
69
69
  isActive: boolean;
70
- category: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform";
71
- productTypes: ("all" | "product" | "auction" | "preorder")[];
70
+ category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
72
71
  displayOrder: number;
72
+ productTypes: ("all" | "product" | "auction" | "preorder")[];
73
73
  description?: string | undefined;
74
74
  iconColor?: string | undefined;
75
75
  }>;
@@ -87,20 +87,20 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
87
87
  label?: string | undefined;
88
88
  icon?: string | undefined;
89
89
  isActive?: boolean | undefined;
90
- category?: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform" | undefined;
90
+ category?: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform" | undefined;
91
91
  description?: string | undefined;
92
92
  iconColor?: string | undefined;
93
- productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
94
93
  displayOrder?: number | undefined;
94
+ productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
95
95
  }, {
96
96
  label?: string | undefined;
97
97
  icon?: string | undefined;
98
98
  isActive?: boolean | undefined;
99
- category?: "seller" | "auction" | "preorder" | "shipping" | "custom" | "condition" | "platform" | undefined;
99
+ category?: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform" | undefined;
100
100
  description?: string | undefined;
101
101
  iconColor?: string | undefined;
102
- productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
103
102
  displayOrder?: number | undefined;
103
+ productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
104
104
  }>;
105
105
  export type ProductFeatureAdminCreatePayload = z.infer<typeof productFeatureAdminCreateSchema>;
106
106
  export type ProductFeatureStoreCreatePayload = z.infer<typeof productFeatureStoreCreateSchema>;
@@ -170,6 +170,8 @@ export interface ProductListParams {
170
170
  dateTo?: string;
171
171
  /** Pre-order production status */
172
172
  preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship";
173
+ /** Prize-draw reveal status */
174
+ prizeRevealStatus?: "pending" | "open" | "closed";
173
175
  /** Filter by brand name */
174
176
  brand?: string;
175
177
  /** Shipping / free shipping */
@@ -6,12 +6,16 @@ import { useUrlTable } from "../../../react/hooks/useUrlTable";
6
6
  import { Pagination, SortDropdown, Div, Text, Heading } from "../../../ui";
7
7
  import { usePromotions } from "../hooks/usePromotions";
8
8
  import { CouponCard } from "./CouponCard";
9
+ import { TABLE_KEYS } from "../../../constants/table-keys";
10
+ import { COUPON_FIELDS } from "../../../constants/field-names";
11
+ import { sortBy } from "../../../constants/sort";
12
+ const DEFAULT_SORT = sortBy(COUPON_FIELDS.CREATED_AT);
9
13
  const COUPON_SORT_OPTIONS = [
10
- { value: "name", label: "Name A–Z" },
11
- { value: "-name", label: "Name Z–A" },
14
+ { value: sortBy(COUPON_FIELDS.NAME, "ASC"), label: "Name A–Z" },
15
+ { value: sortBy(COUPON_FIELDS.NAME), label: "Name Z–A" },
12
16
  { value: "-validity.endDate", label: "Expiring Soon" },
13
- { value: "-createdAt", label: "Newest First" },
14
- { value: "createdAt", label: "Oldest First" },
17
+ { value: sortBy(COUPON_FIELDS.CREATED_AT), label: "Newest First" },
18
+ { value: sortBy(COUPON_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
15
19
  ];
16
20
  const COUPON_TYPES = [
17
21
  { value: "percentage", label: "% Off" },
@@ -20,8 +24,8 @@ const COUPON_TYPES = [
20
24
  { value: "buy_x_get_y", label: "Buy X Get Y" },
21
25
  ];
22
26
  export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
23
- const table = useUrlTable({ defaults: { pageSize: "12", sort: "-createdAt" } });
24
- const [searchInput, setSearchInput] = useState(table.get("q") || "");
27
+ const table = useUrlTable({ defaults: { pageSize: "12", sort: DEFAULT_SORT } });
28
+ const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
25
29
  const [filterOpen, setFilterOpen] = useState(false);
26
30
  // Build Sieve filter string
27
31
  const buildFilters = () => {
@@ -29,10 +33,10 @@ export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
29
33
  const typeFilter = table.get("type");
30
34
  if (typeFilter)
31
35
  parts.push(`type==${typeFilter}`);
32
- const dateFrom = table.get("dateFrom");
36
+ const dateFrom = table.get(TABLE_KEYS.DATE_FROM);
33
37
  if (dateFrom)
34
38
  parts.push(`validity.startDate>=${dateFrom}`);
35
- const dateTo = table.get("dateTo");
39
+ const dateTo = table.get(TABLE_KEYS.DATE_TO);
36
40
  if (dateTo)
37
41
  parts.push(`validity.endDate<=${dateTo}`);
38
42
  if (storeId)
@@ -40,37 +44,37 @@ export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
40
44
  return parts.join(",");
41
45
  };
42
46
  const { promotions: coupons, total, totalPages, isLoading } = usePromotions({
43
- page: table.getNumber("page", 1),
44
- pageSize: table.getNumber("pageSize", 12),
45
- sort: table.get("sort") || "-createdAt",
47
+ page: table.getNumber(TABLE_KEYS.PAGE, 1),
48
+ pageSize: table.getNumber(TABLE_KEYS.PAGE_SIZE, 12),
49
+ sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
46
50
  filters: buildFilters(),
47
51
  });
48
52
  // Use initial data on first load if available and no search/filter active
49
53
  const displayCoupons = !isLoading && coupons.length > 0
50
54
  ? coupons
51
- : !isLoading && initialCoupons && !table.get("q") && !table.get("type")
55
+ : !isLoading && initialCoupons && !table.get(TABLE_KEYS.QUERY) && !table.get("type")
52
56
  ? initialCoupons
53
57
  : coupons;
54
58
  const commitSearch = useCallback(() => {
55
- table.set("q", searchInput.trim());
59
+ table.set(TABLE_KEYS.QUERY, searchInput.trim());
56
60
  }, [searchInput, table]);
57
61
  const handleKeyDown = (e) => {
58
62
  if (e.key === "Enter")
59
63
  commitSearch();
60
64
  };
61
65
  const activeType = table.get("type");
62
- const hasActiveFilters = !!activeType || !!table.get("dateFrom") || !!table.get("dateTo");
66
+ const hasActiveFilters = !!activeType || !!table.get(TABLE_KEYS.DATE_FROM) || !!table.get(TABLE_KEYS.DATE_TO);
63
67
  const clearFilters = () => {
64
- table.setMany({ type: "", dateFrom: "", dateTo: "" });
68
+ table.setMany({ type: "", [TABLE_KEYS.DATE_FROM]: "", [TABLE_KEYS.DATE_TO]: "" });
65
69
  };
66
70
  return (_jsxs("div", { className: "min-h-[40vh]", children: [_jsxs("div", { className: "sticky top-[var(--header-height,0px)] z-20 border-b border-zinc-200 dark:border-slate-700 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm py-2.5 px-4", children: [_jsxs("div", { className: "flex items-center gap-2.5 max-w-full", children: [_jsxs("button", { type: "button", onClick: () => setFilterOpen(true), className: `flex shrink-0 items-center gap-2 rounded-lg border px-3.5 py-2 text-sm font-medium transition-colors ${hasActiveFilters
67
71
  ? "border-primary bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300"
68
- : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs("span", { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set("q", ""); }, className: "p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get("sort") || "-createdAt", onChange: (v) => { table.set("sort", v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mt-2", children: [activeType && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx("button", { type: "button", onClick: () => { table.set("type", ""); }, "aria-label": "Remove type filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get("dateFrom") && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["From: ", table.get("dateFrom"), _jsx("button", { type: "button", onClick: () => { table.set("dateFrom", ""); }, "aria-label": "Remove from-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get("dateTo") && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["To: ", table.get("dateTo"), _jsx("button", { type: "button", onClick: () => { table.set("dateTo", ""); }, "aria-label": "Remove to-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 underline", children: "Clear all" })] }))] }), _jsxs("div", { className: "py-6 px-4", children: [isLoading ? (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border-2 border-zinc-100 dark:border-slate-700 p-4 animate-pulse space-y-3", children: [_jsx("div", { className: "h-6 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx("div", { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No coupons match your search." }) })) : (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
72
+ : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs("span", { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs("div", { className: "flex flex-1 items-center overflow-hidden rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-900", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set(TABLE_KEYS.QUERY, ""); }, className: "p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400", children: [_jsx("span", { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, onChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 mt-2", children: [activeType && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx("button", { type: "button", onClick: () => { table.set("type", ""); }, "aria-label": "Remove type filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs("span", { className: "flex items-center gap-1 rounded-full bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 text-xs font-medium px-2.5 py-1", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx("button", { type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 underline", children: "Clear all" })] }))] }), _jsxs("div", { className: "py-6 px-4", children: [isLoading ? (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border-2 border-zinc-100 dark:border-slate-700 p-4 animate-pulse space-y-3", children: [_jsx("div", { className: "h-6 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-1/2" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx("div", { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-500", children: "No coupons match your search." }) })) : (_jsx("div", { className: "grid gap-3 md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
69
73
  copy: "Copy",
70
74
  copied: "Copied!",
71
75
  expires: "Expires",
72
76
  minOrder: "Min. order",
73
77
  off: "OFF",
74
78
  freeShipping: "Free Shipping",
75
- } }, coupon.id))) })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-6", children: [_jsxs("div", { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Discount Type" }), _jsxs("div", { className: "space-y-2", children: [COUPON_TYPES.map((t) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: table.get("type") === t.value, onChange: () => { table.set("type", t.value); }, className: "accent-primary" }), t.label] }, t.value))), table.get("type") && (_jsx("button", { type: "button", onClick: () => { table.set("type", ""); }, className: "text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 underline", children: "Clear type" }))] })] }), _jsxs("div", { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Valid Date Range" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "From date" }), _jsx("input", { type: "date", value: table.get("dateFrom") || "", onChange: (e) => { table.set("dateFrom", e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "To date" }), _jsx("input", { type: "date", value: table.get("dateTo") || "", onChange: (e) => { table.set("dateTo", e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] })] })] })] }), _jsxs("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5 flex gap-2", children: [_jsx("button", { type: "button", onClick: clearFilters, className: "flex-1 rounded-lg border border-zinc-300 dark:border-slate-600 py-2.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: "Clear all" }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), className: "flex-1 rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply" })] })] })] }))] }));
79
+ } }, coupon.id))) })), totalPages > 1 && (_jsx("div", { className: "mt-8 flex justify-center", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { className: "text-xs text-zinc-400 dark:text-zinc-500", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-6", children: [_jsxs("div", { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Discount Type" }), _jsxs("div", { className: "space-y-2", children: [COUPON_TYPES.map((t) => (_jsxs("label", { className: "flex items-center gap-2 cursor-pointer text-sm text-zinc-700 dark:text-zinc-300", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: table.get("type") === t.value, onChange: () => { table.set("type", t.value); }, className: "accent-primary" }), t.label] }, t.value))), table.get("type") && (_jsx("button", { type: "button", onClick: () => { table.set("type", ""); }, className: "text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 underline", children: "Clear type" }))] })] }), _jsxs("div", { children: [_jsx(Heading, { level: 6, className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: "Valid Date Range" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "From date" }), _jsx("input", { type: "date", value: table.get(TABLE_KEYS.DATE_FROM) || "", onChange: (e) => { table.set(TABLE_KEYS.DATE_FROM, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: "To date" }), _jsx("input", { type: "date", value: table.get(TABLE_KEYS.DATE_TO) || "", onChange: (e) => { table.set(TABLE_KEYS.DATE_TO, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] })] })] })] }), _jsxs("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5 flex gap-2", children: [_jsx("button", { type: "button", onClick: clearFilters, className: "flex-1 rounded-lg border border-zinc-300 dark:border-slate-600 py-2.5 text-sm font-medium text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: "Clear all" }), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), className: "flex-1 rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors", children: "Apply" })] })] })] }))] }));
76
80
  }
@@ -49,10 +49,11 @@ export declare const couponItemSchema: z.ZodObject<{
49
49
  isActive: boolean;
50
50
  isPublic: boolean;
51
51
  description: string;
52
- discountValue: number;
53
52
  usageCount: number;
53
+ discountValue: number;
54
54
  storeId?: string | undefined;
55
55
  expiresAt?: string | undefined;
56
+ startsAt?: string | undefined;
56
57
  minOrderAmount?: number | undefined;
57
58
  maxDiscountAmount?: number | undefined;
58
59
  maxUsageCount?: number | undefined;
@@ -61,7 +62,6 @@ export declare const couponItemSchema: z.ZodObject<{
61
62
  getQuantity?: number | undefined;
62
63
  applicableProductIds?: string[] | undefined;
63
64
  applicableCategoryIds?: string[] | undefined;
64
- startsAt?: string | undefined;
65
65
  }, {
66
66
  id: string;
67
67
  createdAt: string;
@@ -73,10 +73,11 @@ export declare const couponItemSchema: z.ZodObject<{
73
73
  isActive: boolean;
74
74
  isPublic: boolean;
75
75
  description: string;
76
- discountValue: number;
77
76
  usageCount: number;
77
+ discountValue: number;
78
78
  storeId?: string | undefined;
79
79
  expiresAt?: string | undefined;
80
+ startsAt?: string | undefined;
80
81
  minOrderAmount?: number | undefined;
81
82
  maxDiscountAmount?: number | undefined;
82
83
  maxUsageCount?: number | undefined;
@@ -85,7 +86,6 @@ export declare const couponItemSchema: z.ZodObject<{
85
86
  getQuantity?: number | undefined;
86
87
  applicableProductIds?: string[] | undefined;
87
88
  applicableCategoryIds?: string[] | undefined;
88
- startsAt?: string | undefined;
89
89
  }>;
90
90
  export declare const promotionsListParamsSchema: z.ZodObject<{
91
91
  scope: z.ZodOptional<z.ZodEnum<["admin", "seller"]>>;
@@ -2,8 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useCallback } from "react";
4
4
  import Link from "next/link";
5
- import { StarRating } from "../../../ui";
6
- import { RichText } from "../../../ui";
5
+ import { RichText, Span, StarRating } from "../../../ui";
7
6
  import { maskName } from "../../../security";
8
7
  import { getDefaultLocale } from "../../../core/baseline-resolver";
9
8
  import { normalizeRichTextHtml } from "../../../utils/string.formatter";
@@ -70,11 +69,13 @@ export function ReviewDetailShell({ review, storeHref }) {
70
69
  ? String(ROUTES.PUBLIC.PRODUCT_DETAIL(review.productId))
71
70
  : null;
72
71
  const sellerHref = storeHref ?? null;
73
- const reviewerHref = String(ROUTES.PUBLIC.PROFILE(review.userId));
72
+ const reviewerHref = !review.isAnonymous && review.userId
73
+ ? String(ROUTES.PUBLIC.PROFILE(review.userId))
74
+ : null;
74
75
  const currentImage = lightboxIdx !== null ? images[lightboxIdx] : null;
75
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b border-neutral-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 pb-8 pt-10", children: _jsxs("div", { className: "mx-auto max-w-3xl px-4", children: [_jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs("span", { className: "text-2xl font-bold text-neutral-900 dark:text-white", children: [review.rating, ".0"] }), review.verified && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", children: "\u2713 Verified Purchase" })), review.featured && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-yellow-100 px-3 py-1 text-xs font-semibold text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", children: "\u2605 Featured" }))] }), review.title && (_jsx("h1", { className: "text-2xl font-bold text-neutral-900 dark:text-white mb-4 leading-snug", children: review.title })), _jsxs("div", { className: "flex items-center gap-3", children: [review.userAvatar ? (_jsx("div", { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 rounded-full bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-base font-bold text-primary ring-2 ring-white dark:ring-zinc-800", children: initials })), _jsxs("div", { className: "min-w-0", children: [_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-white hover:text-primary transition-colors", children: displayName }), date && (_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mt-0.5", children: date }))] })] })] }) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-8 space-y-8", children: [review.comment && (_jsx("section", { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs("section", { children: [_jsxs("h2", { className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: ["Photos (", images.length, ")"] }), _jsx("div", { className: "grid grid-cols-3 sm:grid-cols-4 gap-2", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("div", { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx("span", { className: "text-white text-xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs("section", { children: [_jsx("h2", { className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: "Video" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-black aspect-video", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs("section", { className: "flex items-center gap-4 py-4 border-t border-neutral-100 dark:border-zinc-800", children: [_jsx("div", { className: "text-sm text-neutral-500 dark:text-zinc-400", children: helpfulCount > 0 && (_jsxs("span", { children: [_jsx("strong", { className: "text-neutral-900 dark:text-white", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
76
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b border-neutral-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 pb-8 pt-10", children: _jsxs("div", { className: "mx-auto max-w-3xl px-4", children: [_jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs("span", { className: "text-2xl font-bold text-neutral-900 dark:text-white", children: [review.rating, ".0"] }), review.verified && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400", children: "\u2713 Verified Purchase" })), review.featured && (_jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-yellow-100 px-3 py-1 text-xs font-semibold text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", children: "\u2605 Featured" }))] }), review.title && (_jsx("h1", { className: "text-2xl font-bold text-neutral-900 dark:text-white mb-4 leading-snug", children: review.title })), _jsxs("div", { className: "flex items-center gap-3", children: [review.userAvatar ? (_jsx("div", { role: "img", "aria-label": displayName, className: "h-11 w-11 flex-shrink-0 rounded-full bg-center bg-cover ring-2 ring-white dark:ring-zinc-800", style: { backgroundImage: `url(${review.userAvatar})` } })) : (_jsx("div", { className: "flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-full bg-primary/10 text-base font-bold text-primary ring-2 ring-white dark:ring-zinc-800", children: initials })), _jsxs("div", { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx("span", { className: "text-sm font-semibold text-neutral-900 dark:text-white", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mt-0.5", children: date }))] })] })] }) }), _jsxs("div", { className: "mx-auto max-w-3xl px-4 py-8 space-y-8", children: [review.comment && (_jsx("section", { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs("section", { children: [_jsxs("h2", { className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: ["Photos (", images.length, ")"] }), _jsx("div", { className: "grid grid-cols-3 sm:grid-cols-4 gap-2", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("div", { className: "h-full w-full bg-center bg-cover transition-transform duration-300 group-hover:scale-105", style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }), _jsx("div", { className: "absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30", children: _jsx("span", { className: "text-white text-xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs("section", { children: [_jsx("h2", { className: "text-sm font-semibold uppercase tracking-wide text-neutral-400 dark:text-zinc-500 mb-3", children: "Video" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-black aspect-video", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs("section", { className: "flex items-center gap-4 py-4 border-t border-neutral-100 dark:border-zinc-800", children: [_jsx("div", { className: "text-sm text-neutral-500 dark:text-zinc-400", children: helpfulCount > 0 && (_jsxs("span", { children: [_jsx("strong", { className: "text-neutral-900 dark:text-white", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
76
77
  ? "border-emerald-200 bg-emerald-50 text-emerald-600 dark:border-emerald-800 dark:bg-emerald-900/20 dark:text-emerald-400 cursor-default"
77
- : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx("span", { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs("section", { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-100 dark:bg-orange-900/30 text-xl", children: "\uD83D\uDCE6" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Product" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-100 dark:bg-blue-900/30 text-xl", children: "\uD83C\uDFEA" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Seller" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: "View Seller" })] })] })), _jsxs(Link, { href: reviewerHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Reviewer" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: displayName })] })] })] })] }), lightboxIdx !== null && currentImage && (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70 text-sm", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx("div", { className: "max-h-[85vh] max-w-[85vw] flex items-center justify-center", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx("div", { className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 px-4", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
78
+ : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx("span", { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs("section", { className: "grid gap-3 sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-100 dark:bg-orange-900/30 text-xl", children: "\uD83D\uDCE6" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Product" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-100 dark:bg-blue-900/30 text-xl", children: "\uD83C\uDFEA" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Seller" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Reviewer" }), _jsx("p", { className: "text-sm font-medium text-neutral-900 dark:text-white truncate group-hover:text-primary transition-colors", children: displayName })] })] })) : (_jsxs("div", { className: "flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4", children: [_jsx("span", { className: "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-100 dark:bg-purple-900/30 text-xl", children: "\uD83D\uDC64" }), _jsxs("div", { className: "min-w-0", children: [_jsx(Span, { className: "block text-xs text-neutral-400 dark:text-zinc-500 mb-0.5", children: "Reviewer" }), _jsx(Span, { className: "block text-sm font-medium text-neutral-900 dark:text-white truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/95", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70 text-sm", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx("div", { className: "max-h-[85vh] max-w-[85vw] flex items-center justify-center", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx("div", { className: "absolute bottom-4 left-0 right-0 flex justify-center gap-2 px-4", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md bg-center bg-cover border-2 transition-all ${i === lightboxIdx
78
79
  ? "border-white scale-110"
79
80
  : "border-transparent opacity-60 hover:opacity-100"}`, style: { backgroundImage: `url(${img.thumbnailUrl ?? img.url})` } }, i))) }))] }))] }));
80
81
  }
@@ -7,55 +7,55 @@ export declare const REVIEW_FILTER_KEYS: {
7
7
  readonly public: readonly ["rating", "brand", "dateFrom", "dateTo"];
8
8
  };
9
9
  export declare const REVIEW_ADMIN_SORT_OPTIONS: readonly [{
10
- readonly value: "-createdAt";
10
+ readonly value: string;
11
11
  readonly key: "sortNewest";
12
12
  }, {
13
- readonly value: "createdAt";
13
+ readonly value: string;
14
14
  readonly key: "sortOldest";
15
15
  }, {
16
- readonly value: "-rating";
16
+ readonly value: string;
17
17
  readonly key: "sortHighestRated";
18
18
  }, {
19
- readonly value: "rating";
19
+ readonly value: string;
20
20
  readonly key: "sortLowestRated";
21
21
  }];
22
22
  export declare const REVIEW_SELLER_SORT_OPTIONS: readonly [{
23
- readonly value: "-createdAt";
23
+ readonly value: string;
24
24
  readonly key: "sortNewest";
25
25
  }, {
26
- readonly value: "createdAt";
26
+ readonly value: string;
27
27
  readonly key: "sortOldest";
28
28
  }, {
29
- readonly value: "-rating";
29
+ readonly value: string;
30
30
  readonly key: "sortHighestRated";
31
31
  }, {
32
- readonly value: "rating";
32
+ readonly value: string;
33
33
  readonly key: "sortLowestRated";
34
34
  }];
35
35
  export declare const REVIEW_PUBLIC_SORT_OPTIONS: readonly [{
36
- readonly value: "-createdAt";
36
+ readonly value: string;
37
37
  readonly key: "sortNewest";
38
38
  }, {
39
- readonly value: "createdAt";
39
+ readonly value: string;
40
40
  readonly key: "sortOldest";
41
41
  }, {
42
- readonly value: "-rating";
42
+ readonly value: string;
43
43
  readonly key: "sortHighestRated";
44
44
  }, {
45
- readonly value: "rating";
45
+ readonly value: string;
46
46
  readonly key: "sortLowestRated";
47
47
  }];
48
48
  export declare const REVIEW_SORT_OPTIONS: readonly [{
49
- readonly value: "-createdAt";
49
+ readonly value: string;
50
50
  readonly key: "sortNewest";
51
51
  }, {
52
- readonly value: "createdAt";
52
+ readonly value: string;
53
53
  readonly key: "sortOldest";
54
54
  }, {
55
- readonly value: "-rating";
55
+ readonly value: string;
56
56
  readonly key: "sortHighestRated";
57
57
  }, {
58
- readonly value: "rating";
58
+ readonly value: string;
59
59
  readonly key: "sortLowestRated";
60
60
  }];
61
61
  export declare function getReviewFilterKeys(variant: ReviewFilterVariant): readonly string[];
@@ -5,16 +5,19 @@ import { FilterFacetSection } from "../../filters/FilterFacetSection";
5
5
  import { RangeFilter } from "../../filters/RangeFilter";
6
6
  import { SwitchFilter } from "../../filters/SwitchFilter";
7
7
  import { Div } from "../../../ui";
8
+ import { TABLE_KEYS } from "../../../constants/table-keys";
9
+ import { REVIEW_FIELDS } from "../../../constants/field-names";
10
+ import { sortBy } from "../../../constants/sort";
8
11
  export const REVIEW_FILTER_KEYS = {
9
- admin: ["status", "rating", "brand", "verified", "featured", "dateFrom", "dateTo"],
10
- seller: ["status", "rating", "brand", "dateFrom", "dateTo"],
11
- public: ["rating", "brand", "dateFrom", "dateTo"],
12
+ admin: [TABLE_KEYS.STATUS, TABLE_KEYS.RATING, TABLE_KEYS.BRAND, "verified", TABLE_KEYS.FEATURED, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO],
13
+ seller: [TABLE_KEYS.STATUS, TABLE_KEYS.RATING, TABLE_KEYS.BRAND, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO],
14
+ public: [TABLE_KEYS.RATING, TABLE_KEYS.BRAND, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO],
12
15
  };
13
16
  export const REVIEW_ADMIN_SORT_OPTIONS = [
14
- { value: "-createdAt", key: "sortNewest" },
15
- { value: "createdAt", key: "sortOldest" },
16
- { value: "-rating", key: "sortHighestRated" },
17
- { value: "rating", key: "sortLowestRated" },
17
+ { value: sortBy(REVIEW_FIELDS.CREATED_AT), key: "sortNewest" },
18
+ { value: sortBy(REVIEW_FIELDS.CREATED_AT, "ASC"), key: "sortOldest" },
19
+ { value: sortBy(REVIEW_FIELDS.RATING), key: "sortHighestRated" },
20
+ { value: sortBy(REVIEW_FIELDS.RATING, "ASC"), key: "sortLowestRated" },
18
21
  ];
19
22
  export const REVIEW_SELLER_SORT_OPTIONS = REVIEW_ADMIN_SORT_OPTIONS;
20
23
  export const REVIEW_PUBLIC_SORT_OPTIONS = REVIEW_ADMIN_SORT_OPTIONS;