@mohasinac/appkit 4.11.2 → 4.12.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 (246) hide show
  1. package/dist/_internal/server/features/checkout/actions.d.ts +40 -3
  2. package/dist/_internal/server/features/checkout/actions.js +232 -47
  3. package/dist/_internal/server/features/checkout/data.d.ts +10 -0
  4. package/dist/_internal/server/features/orders/adapters.js +20 -0
  5. package/dist/_internal/server/features/products/data.d.ts +12 -3
  6. package/dist/_internal/server/features/products/data.js +55 -4
  7. package/dist/_internal/server/features/products/index.d.ts +1 -1
  8. package/dist/_internal/server/features/products/index.js +1 -1
  9. package/dist/_internal/server/features/products/list-public.d.ts +47 -0
  10. package/dist/_internal/server/features/products/list-public.js +131 -6
  11. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  12. package/dist/_internal/server/features/reviews/data.js +3 -2
  13. package/dist/_internal/server/features/tester/visibility.js +3 -3
  14. package/dist/_internal/server/jobs/core/auctionSettlement.js +5 -2
  15. package/dist/_internal/server/jobs/core/testerSandboxCleanup.d.ts +1 -1
  16. package/dist/_internal/server/jobs/core/testerSandboxCleanup.js +4 -1
  17. package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +2 -0
  18. package/dist/_internal/server/jobs/handlers/_helpers.js +4 -1
  19. package/dist/_internal/shared/checkout/lanes.d.ts +20 -0
  20. package/dist/_internal/shared/checkout/lanes.js +28 -0
  21. package/dist/_internal/shared/features/checkout/config.d.ts +4 -0
  22. package/dist/_internal/shared/features/checkout/config.js +8 -0
  23. package/dist/_internal/shared/features/promotions/schema.d.ts +0 -16
  24. package/dist/_internal/shared/features/promotions/schema.js +0 -2
  25. package/dist/_internal/shared/features/reviews/config.d.ts +8 -1
  26. package/dist/_internal/shared/features/reviews/config.js +8 -1
  27. package/dist/_internal/shared/fees/calculator.d.ts +34 -2
  28. package/dist/_internal/shared/fees/calculator.js +45 -1
  29. package/dist/_internal/shared/listing-types/_registry.d.ts +88 -1
  30. package/dist/_internal/shared/listing-types/_registry.js +63 -1
  31. package/dist/_internal/shared/listing-types/art/config.d.ts +59 -0
  32. package/dist/_internal/shared/listing-types/art/config.js +12 -0
  33. package/dist/_internal/shared/listing-types/auction/config.d.ts +53 -0
  34. package/dist/_internal/shared/listing-types/auction/config.js +17 -0
  35. package/dist/_internal/shared/listing-types/classified/config.d.ts +59 -0
  36. package/dist/_internal/shared/listing-types/classified/config.js +14 -0
  37. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +59 -0
  38. package/dist/_internal/shared/listing-types/digital-code/config.js +12 -0
  39. package/dist/_internal/shared/listing-types/live/config.d.ts +59 -0
  40. package/dist/_internal/shared/listing-types/live/config.js +14 -0
  41. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +110 -0
  42. package/dist/_internal/shared/listing-types/pre-order/config.js +14 -0
  43. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +44 -0
  44. package/dist/_internal/shared/listing-types/prize-draw/config.js +10 -0
  45. package/dist/_internal/shared/listing-types/standard/config.d.ts +59 -0
  46. package/dist/_internal/shared/listing-types/standard/config.js +9 -0
  47. package/dist/_internal/shared/listing-types/stickers/config.d.ts +59 -0
  48. package/dist/_internal/shared/listing-types/stickers/config.js +12 -0
  49. package/dist/client.d.ts +12 -2
  50. package/dist/client.js +8 -2
  51. package/dist/constants/api-endpoints.d.ts +6 -0
  52. package/dist/constants/api-endpoints.js +2 -0
  53. package/dist/constants/field-names.d.ts +12 -0
  54. package/dist/constants/field-names.js +12 -0
  55. package/dist/constants/table-keys.d.ts +2 -0
  56. package/dist/constants/table-keys.js +2 -0
  57. package/dist/features/account/components/UserOrdersView.js +27 -5
  58. package/dist/features/admin/components/AdminAddressesView.js +21 -11
  59. package/dist/features/admin/components/AdminArtView.d.ts +9 -0
  60. package/dist/features/admin/components/AdminArtView.js +11 -35
  61. package/dist/features/admin/components/AdminClassifiedView.d.ts +9 -0
  62. package/dist/features/admin/components/AdminClassifiedView.js +11 -35
  63. package/dist/features/admin/components/AdminCouponEditorView.js +1 -4
  64. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +9 -0
  65. package/dist/features/admin/components/AdminDigitalCodesView.js +11 -42
  66. package/dist/features/admin/components/AdminLiveView.d.ts +9 -0
  67. package/dist/features/admin/components/AdminLiveView.js +11 -41
  68. package/dist/features/admin/components/AdminOrderEditorView.d.ts +8 -1
  69. package/dist/features/admin/components/AdminOrderEditorView.js +4 -3
  70. package/dist/features/admin/components/AdminOrdersView.js +14 -1
  71. package/dist/features/admin/components/AdminPaymentMethodsView.js +18 -11
  72. package/dist/features/admin/components/AdminProductsView.js +34 -18
  73. package/dist/features/admin/components/AdminSiteConfigGuideView.js +1 -1
  74. package/dist/features/admin/components/AdminSiteSettingsView.js +4 -2
  75. package/dist/features/admin/components/AdminStickersView.d.ts +9 -0
  76. package/dist/features/admin/components/AdminStickersView.js +11 -35
  77. package/dist/features/admin/constants/filter-tabs.d.ts +26 -9
  78. package/dist/features/admin/constants/filter-tabs.js +22 -9
  79. package/dist/features/admin/hooks/useAdminListing.js +7 -2
  80. package/dist/features/admin/schemas/firestore.d.ts +5 -0
  81. package/dist/features/admin/schemas/firestore.js +1 -0
  82. package/dist/features/auctions/actions/bid-actions.js +2 -2
  83. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  84. package/dist/features/auctions/components/AuctionBottomActions.js +1 -0
  85. package/dist/features/auctions/components/AuctionDetailPageView.js +13 -11
  86. package/dist/features/cart/components/CartDrawer.d.ts +9 -1
  87. package/dist/features/cart/components/CartDrawer.js +4 -3
  88. package/dist/features/cart/components/CartPriceBreakdown.d.ts +61 -0
  89. package/dist/features/cart/components/CartPriceBreakdown.js +25 -0
  90. package/dist/features/cart/components/StoreAddonsPicker.d.ts +47 -0
  91. package/dist/features/cart/components/StoreAddonsPicker.js +21 -0
  92. package/dist/features/cart/components/index.d.ts +4 -0
  93. package/dist/features/cart/components/index.js +2 -0
  94. package/dist/features/cart/repository/cart.repository.d.ts +20 -2
  95. package/dist/features/cart/repository/cart.repository.js +49 -0
  96. package/dist/features/cart/schemas/firestore.d.ts +26 -2
  97. package/dist/features/categories/components/BrandDetailTabs.js +31 -11
  98. package/dist/features/categories/components/CategoryDetailTabs.js +27 -7
  99. package/dist/features/categories/components/CategoryProductsListing.d.ts +9 -1
  100. package/dist/features/categories/components/CategoryProductsListing.js +5 -2
  101. package/dist/features/classified/components/ClassifiedDetailPageView.js +2 -1
  102. package/dist/features/contact/email.js +5 -1
  103. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +17 -16
  104. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  105. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  106. package/dist/features/homepage/components/ShopByCategorySection.js +1 -1
  107. package/dist/features/layout/AppLayoutShell.js +9 -2
  108. package/dist/features/layout/BottomActions.js +62 -6
  109. package/dist/features/layout/BottomActionsContext.d.ts +26 -0
  110. package/dist/features/layout/BottomActionsContext.js +18 -1
  111. package/dist/features/layout/hooks/useBottomActions.d.ts +12 -1
  112. package/dist/features/layout/hooks/useBottomActions.js +14 -1
  113. package/dist/features/layout/index.d.ts +1 -1
  114. package/dist/features/live/components/LiveItemDetailPageView.js +7 -6
  115. package/dist/features/orders/components/OrderAddonBadges.d.ts +36 -0
  116. package/dist/features/orders/components/OrderAddonBadges.js +28 -0
  117. package/dist/features/orders/components/index.d.ts +1 -0
  118. package/dist/features/orders/components/index.js +1 -0
  119. package/dist/features/orders/repository/orders.repository.d.ts +36 -0
  120. package/dist/features/orders/repository/orders.repository.js +18 -0
  121. package/dist/features/orders/types/index.d.ts +38 -0
  122. package/dist/features/pre-orders/components/PreOrderBottomActions.d.ts +1 -1
  123. package/dist/features/pre-orders/components/PreOrderBottomActions.js +3 -19
  124. package/dist/features/products/components/ArtStickersListView.js +5 -4
  125. package/dist/features/products/components/AuctionsIndexListing.js +1 -2
  126. package/dist/features/products/components/ListingBottomActions.d.ts +28 -0
  127. package/dist/features/products/components/ListingBottomActions.js +25 -0
  128. package/dist/features/products/components/PrizeDrawBottomActions.d.ts +1 -1
  129. package/dist/features/products/components/PrizeDrawBottomActions.js +3 -21
  130. package/dist/features/products/components/PrizeDrawsListingView.js +18 -33
  131. package/dist/features/products/components/ProductDetailActions.js +4 -0
  132. package/dist/features/products/components/ProductDetailPageView.js +7 -7
  133. package/dist/features/products/components/ProductsIndexListing.js +87 -11
  134. package/dist/features/products/components/ProductsIndexPageView.js +14 -2
  135. package/dist/features/products/config/listing-type-listing-config.d.ts +31 -0
  136. package/dist/features/products/config/listing-type-listing-config.js +74 -0
  137. package/dist/features/products/constants/listing-tabs.d.ts +43 -198
  138. package/dist/features/products/constants/listing-tabs.js +71 -58
  139. package/dist/features/products/constants/sieve.d.ts +104 -1
  140. package/dist/features/products/constants/sieve.js +27 -7
  141. package/dist/features/products/hooks/useProducts.js +14 -0
  142. package/dist/features/products/repository/products.repository.d.ts +45 -1
  143. package/dist/features/products/repository/products.repository.js +26 -3
  144. package/dist/features/products/types/index.d.ts +15 -0
  145. package/dist/features/products/utils/listing-badge-variant.d.ts +20 -1
  146. package/dist/features/products/utils/listing-badge-variant.js +26 -1
  147. package/dist/features/products/utils/listing-type.d.ts +24 -0
  148. package/dist/features/products/utils/listing-type.js +48 -0
  149. package/dist/features/promotions/actions/coupon-actions.d.ts +7 -0
  150. package/dist/features/promotions/actions/coupon-actions.js +12 -1
  151. package/dist/features/promotions/actions/coupon-stacking.d.ts +24 -0
  152. package/dist/features/promotions/actions/coupon-stacking.js +21 -0
  153. package/dist/features/promotions/actions/index.d.ts +1 -0
  154. package/dist/features/promotions/actions/index.js +1 -0
  155. package/dist/features/promotions/actions/seller-coupon-actions.d.ts +0 -1
  156. package/dist/features/promotions/actions/seller-coupon-actions.js +0 -1
  157. package/dist/features/promotions/components/CouponHelpDetails.d.ts +20 -0
  158. package/dist/features/promotions/components/CouponHelpDetails.js +17 -0
  159. package/dist/features/promotions/components/CouponsIndexListing.js +2 -1
  160. package/dist/features/promotions/components/index.d.ts +2 -0
  161. package/dist/features/promotions/components/index.js +1 -0
  162. package/dist/features/promotions/constants/coupon-help.d.ts +27 -0
  163. package/dist/features/promotions/constants/coupon-help.js +42 -0
  164. package/dist/features/promotions/repository/coupons.repository.d.ts +10 -1
  165. package/dist/features/promotions/repository/coupons.repository.js +22 -8
  166. package/dist/features/promotions/schemas/firestore.d.ts +0 -1
  167. package/dist/features/promotions/schemas/firestore.js +1 -1
  168. package/dist/features/promotions/schemas/index.d.ts +0 -20
  169. package/dist/features/promotions/schemas/index.js +0 -1
  170. package/dist/features/reviews/actions/review-actions.js +5 -1
  171. package/dist/features/reviews/components/ReviewDetailPageView.js +2 -1
  172. package/dist/features/reviews/components/ReviewFilters.d.ts +7 -1
  173. package/dist/features/reviews/components/ReviewFilters.js +4 -3
  174. package/dist/features/reviews/components/ReviewsIndexListing.d.ts +6 -0
  175. package/dist/features/reviews/components/ReviewsIndexListing.js +9 -109
  176. package/dist/features/reviews/components/ReviewsListingPanel.d.ts +41 -0
  177. package/dist/features/reviews/components/ReviewsListingPanel.js +226 -0
  178. package/dist/features/reviews/components/index.d.ts +2 -0
  179. package/dist/features/reviews/components/index.js +1 -0
  180. package/dist/features/reviews/hooks/useReviews.d.ts +8 -0
  181. package/dist/features/reviews/hooks/useReviews.js +14 -6
  182. package/dist/features/reviews/repository/reviews.repository.d.ts +29 -1
  183. package/dist/features/reviews/repository/reviews.repository.js +77 -41
  184. package/dist/features/reviews/types/index.d.ts +8 -1
  185. package/dist/features/seller/components/SellerOrdersView.js +2 -1
  186. package/dist/features/seller/components/SellerProductsCards.js +2 -2
  187. package/dist/features/seller/components/SellerProductsView.js +21 -18
  188. package/dist/features/stores/actions/store-query-actions.js +1 -1
  189. package/dist/features/stores/components/StoreArtStickersPageView.d.ts +21 -0
  190. package/dist/features/stores/components/StoreArtStickersPageView.js +30 -0
  191. package/dist/features/stores/components/StoreAuctionsListing.js +5 -11
  192. package/dist/features/stores/components/StoreAuctionsPageView.d.ts +4 -1
  193. package/dist/features/stores/components/StoreAuctionsPageView.js +17 -17
  194. package/dist/features/stores/components/StoreClassifiedsListing.js +7 -0
  195. package/dist/features/stores/components/StoreClassifiedsPageView.d.ts +4 -1
  196. package/dist/features/stores/components/StoreClassifiedsPageView.js +16 -12
  197. package/dist/features/stores/components/StoreDetailLayoutView.js +4 -3
  198. package/dist/features/stores/components/StoreDigitalCodesListing.js +5 -0
  199. package/dist/features/stores/components/StoreDigitalCodesPageView.d.ts +4 -1
  200. package/dist/features/stores/components/StoreDigitalCodesPageView.js +16 -12
  201. package/dist/features/stores/components/StoreLiveItemsListing.js +7 -0
  202. package/dist/features/stores/components/StoreLiveItemsPageView.d.ts +4 -1
  203. package/dist/features/stores/components/StoreLiveItemsPageView.js +16 -12
  204. package/dist/features/stores/components/StorePreOrdersListing.js +6 -11
  205. package/dist/features/stores/components/StorePreOrdersPageView.d.ts +4 -1
  206. package/dist/features/stores/components/StorePreOrdersPageView.js +17 -17
  207. package/dist/features/stores/components/StorePrizeDrawsPageView.d.ts +4 -8
  208. package/dist/features/stores/components/StorePrizeDrawsPageView.js +17 -22
  209. package/dist/features/stores/components/StoreProductsListing.d.ts +7 -1
  210. package/dist/features/stores/components/StoreProductsListing.js +3 -2
  211. package/dist/features/stores/components/StoreProductsPageView.d.ts +1 -1
  212. package/dist/features/stores/components/StoreProductsPageView.js +16 -21
  213. package/dist/features/stores/components/StoreReviewsListing.d.ts +4 -0
  214. package/dist/features/stores/components/StoreReviewsListing.js +7 -108
  215. package/dist/features/stores/schemas/index.d.ts +2 -2
  216. package/dist/features/tester/seed-data/coupons-tester-seed-data.js +3 -3
  217. package/dist/features/tester/seed-data/index.d.ts +1 -0
  218. package/dist/features/tester/seed-data/index.js +1 -0
  219. package/dist/features/tester/seed-data/offers-tester-seed-data.d.ts +2 -0
  220. package/dist/features/tester/seed-data/offers-tester-seed-data.js +61 -0
  221. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +939 -1
  222. package/dist/index.d.ts +9 -3
  223. package/dist/index.js +11 -2
  224. package/dist/next/routing/route-map.d.ts +2 -0
  225. package/dist/next/routing/route-map.js +5 -0
  226. package/dist/react/hooks/useListingTypeFlags.d.ts +12 -19
  227. package/dist/react/hooks/useListingTypeFlags.js +4 -9
  228. package/dist/schemas/registry.d.ts +0 -12
  229. package/dist/seed/claimed-coupons-seed-data.js +3 -3
  230. package/dist/seed/coupons-seed-data.js +29 -10
  231. package/dist/seed/faq-seed-data.js +2 -2
  232. package/dist/seed/manifest.js +2 -2
  233. package/dist/seed/reviews-seed-data.js +52 -0
  234. package/dist/server-entry.d.ts +1 -0
  235. package/dist/server-entry.js +1 -0
  236. package/dist/styles.css +55 -39
  237. package/dist/tailwind-utilities.css +1 -1
  238. package/dist/ui/components/Checkbox.d.ts +10 -1
  239. package/dist/ui/components/Checkbox.js +14 -2
  240. package/dist/ui/components/Checkbox.style.css +11 -0
  241. package/dist/ui/components/FilterChipGroup.d.ts +21 -3
  242. package/dist/ui/components/FilterChipGroup.js +33 -4
  243. package/dist/ui/components/HorizontalScroller.d.ts +1 -2
  244. package/dist/ui/components/HorizontalScroller.js +9 -5
  245. package/dist/ui/components/HorizontalScroller.style.css +43 -38
  246. package/package.json +1 -1
@@ -12,7 +12,6 @@ export const createCouponSchema = z.object({
12
12
  name: z.string().min(1).max(100),
13
13
  type: z.enum(["percentage", "fixed", "free_shipping", "buy_x_get_y"]),
14
14
  scope: z.enum(["admin", "seller"]),
15
- sellerId: z.string().optional(),
16
15
  discount: z.object({
17
16
  value: z.number().min(0),
18
17
  maxDiscount: z.number().min(0).optional(),
@@ -29,7 +28,6 @@ export const createCouponSchema = z.object({
29
28
  }),
30
29
  restrictions: z.object({
31
30
  firstTimeUserOnly: z.boolean().default(false),
32
- combineWithSellerCoupons: z.boolean().default(false),
33
31
  applicableProducts: z.array(z.string()).optional(),
34
32
  applicableCategories: z.array(z.string()).optional(),
35
33
  }).optional(),
@@ -1,4 +1,11 @@
1
- export declare const REVIEWS_PAGE_SIZE = 20;
1
+ /** Page size for the dedicated review listing surfaces (`/reviews`, `/stores/[slug]/reviews`). */
2
+ export declare const REVIEWS_PAGE_SIZE = 12;
3
+ /**
4
+ * Page size for the reviews section embedded in a listing detail page. Smaller than
5
+ * REVIEWS_PAGE_SIZE on purpose — the tab sits inside a page that already has a lot of
6
+ * content, and an unpaginated list was what made those pages endlessly long.
7
+ */
8
+ export declare const REVIEWS_DETAIL_PAGE_SIZE = 10;
2
9
  export declare const REVIEW_BODY_MAX_LENGTH = 2000;
3
10
  export declare const REVIEW_TITLE_MAX_LENGTH = 100;
4
11
  export declare const REVIEW_MIN_RATING = 1;
@@ -1,4 +1,11 @@
1
- export const REVIEWS_PAGE_SIZE = 20;
1
+ /** Page size for the dedicated review listing surfaces (`/reviews`, `/stores/[slug]/reviews`). */
2
+ export const REVIEWS_PAGE_SIZE = 12;
3
+ /**
4
+ * Page size for the reviews section embedded in a listing detail page. Smaller than
5
+ * REVIEWS_PAGE_SIZE on purpose — the tab sits inside a page that already has a lot of
6
+ * content, and an unpaginated list was what made those pages endlessly long.
7
+ */
8
+ export const REVIEWS_DETAIL_PAGE_SIZE = 10;
2
9
  export const REVIEW_BODY_MAX_LENGTH = 2000;
3
10
  export const REVIEW_TITLE_MAX_LENGTH = 100;
4
11
  export const REVIEW_MIN_RATING = 1;
@@ -18,17 +18,49 @@ export interface FeeCommissionRates {
18
18
  platformFeePercent: number;
19
19
  gstPercent: number;
20
20
  /** Rupee floor (not paise) — matches the existing `minimumTransactionFee` doc convention. */ minimumTransactionFee?: number;
21
+ /**
22
+ * Rupee ceiling on the buyer-facing platform commission. Optional so
23
+ * siteSettings documents saved before this field existed keep working —
24
+ * falls back to DEFAULT_PLATFORM_FEE_MAX (₹10).
25
+ *
26
+ * Applies to `computeCheckoutFees` (what the BUYER pays) only. The seller-side
27
+ * `computePayoutDeduction` is deliberately uncapped — that is a separate
28
+ * commercial decision, not the same number.
29
+ */ platformFeeMax?: number;
21
30
  gatewayFeePercent?: number;
22
31
  }
23
32
  export interface CheckoutFees {
24
- /** Platform commission in decimal rupees. */
33
+ /** Platform commission in decimal rupees, capped at `platformFeeMax`. */
25
34
  platformFee: number;
26
- /** GST on the platform fee, in decimal rupees. */
35
+ /** GST on the (already capped) platform fee, in decimal rupees. */
27
36
  gstOnFee: number;
28
37
  /** platformFee + gstOnFee, floored at minimumTransactionFee. */
29
38
  totalFee: number;
30
39
  }
40
+ /**
41
+ * What the buyer pays on top of the subtotal.
42
+ *
43
+ * The cap is applied to the commission BEFORE GST is computed, because GST is
44
+ * levied on the commission actually charged — capping afterwards would bill tax
45
+ * on money that was never collected.
46
+ */
31
47
  export declare function computeCheckoutFees(subtotal: number, commissions: FeeCommissionRates): CheckoutFees;
48
+ /**
49
+ * Split one checkout's platform commission across the orders it produces.
50
+ *
51
+ * The buyer is charged a single capped commission for the transaction, but the
52
+ * cart splits into one order per store, and each `OrderDocument` records its own
53
+ * `platformFee` (invoices, reconciliation). Apportioning pro-rata by group
54
+ * subtotal keeps those per-order figures meaningful; giving the last group the
55
+ * rounding remainder guarantees they sum to exactly what was charged, so the
56
+ * orders can never quietly total a rupee more or less than the buyer paid.
57
+ *
58
+ * @param groupSubtotals `[storeId, subtotal]` pairs, in stable order.
59
+ */
60
+ export declare function allocateCheckoutFees(groupSubtotals: readonly (readonly [string, number])[], fees: CheckoutFees): Map<string, {
61
+ platformFee: number;
62
+ gstOnFee: number;
63
+ }>;
32
64
  export interface PayoutDeduction {
33
65
  /** Platform commission in decimal rupees. */
34
66
  platformFee: number;
@@ -15,12 +15,56 @@
15
15
  * All money amounts are in decimal rupees.
16
16
  */
17
17
  import { roundRupees } from "../../../utils/number.formatter";
18
+ /** Buyer-facing platform commission ceiling, in decimal rupees. */
19
+ const DEFAULT_PLATFORM_FEE_MAX = 10;
20
+ /**
21
+ * What the buyer pays on top of the subtotal.
22
+ *
23
+ * The cap is applied to the commission BEFORE GST is computed, because GST is
24
+ * levied on the commission actually charged — capping afterwards would bill tax
25
+ * on money that was never collected.
26
+ */
18
27
  export function computeCheckoutFees(subtotal, commissions) {
19
- const platformFee = roundRupees(subtotal * (commissions.platformFeePercent / 100));
28
+ const uncapped = roundRupees(subtotal * (commissions.platformFeePercent / 100));
29
+ const cap = commissions.platformFeeMax ?? DEFAULT_PLATFORM_FEE_MAX;
30
+ const platformFee = Math.min(uncapped, cap);
20
31
  const gstOnFee = roundRupees(platformFee * (commissions.gstPercent / 100));
21
32
  const totalFee = Math.max(platformFee + gstOnFee, commissions.minimumTransactionFee ?? 0);
22
33
  return { platformFee, gstOnFee, totalFee };
23
34
  }
35
+ /**
36
+ * Split one checkout's platform commission across the orders it produces.
37
+ *
38
+ * The buyer is charged a single capped commission for the transaction, but the
39
+ * cart splits into one order per store, and each `OrderDocument` records its own
40
+ * `platformFee` (invoices, reconciliation). Apportioning pro-rata by group
41
+ * subtotal keeps those per-order figures meaningful; giving the last group the
42
+ * rounding remainder guarantees they sum to exactly what was charged, so the
43
+ * orders can never quietly total a rupee more or less than the buyer paid.
44
+ *
45
+ * @param groupSubtotals `[storeId, subtotal]` pairs, in stable order.
46
+ */
47
+ export function allocateCheckoutFees(groupSubtotals, fees) {
48
+ const allocation = new Map();
49
+ if (groupSubtotals.length === 0)
50
+ return allocation;
51
+ const total = groupSubtotals.reduce((sum, [, subtotal]) => sum + subtotal, 0);
52
+ let platformRemaining = fees.platformFee;
53
+ let gstRemaining = fees.gstOnFee;
54
+ groupSubtotals.forEach(([storeId, subtotal], index) => {
55
+ const isLast = index === groupSubtotals.length - 1;
56
+ // An all-zero cart can't be apportioned by share — fall back to giving the
57
+ // whole (necessarily zero-ish) fee to the last group rather than dividing
58
+ // by zero.
59
+ const share = total > 0 ? subtotal / total : 0;
60
+ const platformFee = isLast ? roundRupees(platformRemaining) : roundRupees(fees.platformFee * share);
61
+ const gstOnFee = isLast ? roundRupees(gstRemaining) : roundRupees(fees.gstOnFee * share);
62
+ platformRemaining = roundRupees(platformRemaining - platformFee);
63
+ gstRemaining = roundRupees(gstRemaining - gstOnFee);
64
+ allocation.set(storeId, { platformFee, gstOnFee });
65
+ });
66
+ return allocation;
67
+ }
24
68
  export function computePayoutDeduction(grossAmount, commissions) {
25
69
  const platformFee = roundRupees(grossAmount * (commissions.platformFeePercent / 100));
26
70
  const gatewayFee = roundRupees(grossAmount * ((commissions.gatewayFeePercent ?? 0) / 100));
@@ -4,12 +4,37 @@
4
4
  * Adding a new listing type later means:
5
5
  * 1. Add a folder `<type>/{config,schema,ctas,og,seed-factory}.ts`
6
6
  * 2. Add a row to `LISTING_TYPE_CAPABILITIES` in `./capabilities.ts`
7
- * 3. Add the import + entry below
7
+ * 3. Add a row to `ALL_LISTING_TYPES_MAP` in `./feature-flags.ts`
8
+ * 4. Add the import + entry below
8
9
  *
9
10
  * No grep-the-codebase sweep required. Future-expansion Pattern 3.
11
+ *
12
+ * BROWSE CHROME (2026-08-21) — the plugin also carries the tab/sort/filter
13
+ * metadata every listing surface needs, so tab bars, chip groups, sort
14
+ * dropdowns and filter drawers are DERIVED from this one map instead of
15
+ * hand-copied. Before this, at least nine independent "list every listing
16
+ * type" arrays existed (tab constants, admin type-filter maps, the seller
17
+ * TypeDropdown, useListingTypeFlags, SORT_OPTIONS_BY_LISTING_TYPE, …) and
18
+ * they had silently drifted: `art` and `stickers` were missing from most of
19
+ * them, `bundle` — which stopped being a listingType in SB-UNI-D — was still
20
+ * present in others, and the public /products chips offered only 4 of 9
21
+ * types. `scripts/audit-listing-type-tab-coverage.mjs` now blocks any array
22
+ * that doesn't cover the full union.
10
23
  */
11
24
  import { LISTING_TYPE_CAPABILITIES } from "./capabilities";
12
25
  import type { ListingType } from "../../../features/products/types/index";
26
+ import type { SortOption } from "../../../features/products/constants/sieve";
27
+ /**
28
+ * Which "Show X" quick-filter a listing type's browse surfaces default to
29
+ * hiding. Drives both the toolbar toggle label and the SSR default filter,
30
+ * which MUST agree or the first paint disagrees with the first refetch
31
+ * (Root Cause #30).
32
+ *
33
+ * "sold" — hide rows with no stock (`inStock`)
34
+ * "ended" — hide rows whose end date has passed (`dateFrom` = now)
35
+ * "closed" — hide rows that stopped accepting entries/orders
36
+ */
37
+ export type ListingHideDefault = "sold" | "ended" | "closed";
13
38
  export interface ListingTypePlugin {
14
39
  listingType: ListingType;
15
40
  slugPrefix: string;
@@ -27,6 +52,44 @@ export interface ListingTypePlugin {
27
52
  typeLabel: string;
28
53
  /** Whether the seller create/edit form shows a Stock Quantity field. */
29
54
  showsStockQuantity: boolean;
55
+ /**
56
+ * URL-facing tab slug — the segment in `/stores/{slug}/<tabSlug>` and the
57
+ * `id` of every route-backed tab bar (category, brand, store, seller).
58
+ *
59
+ * DELIBERATELY NOT the same id space as `listingType`: these slugs are
60
+ * plural-kebab ("pre-orders", "digital-codes") and are baked into live URLs
61
+ * and bookmarks, whereas `listingType` is the canonical singular value that
62
+ * goes straight into a Firestore `==` filter. Tab bars key on `tabSlug`;
63
+ * filter chips key on `listingType`. Conflating them either breaks existing
64
+ * URLs or silently returns zero rows (Root Cause #33).
65
+ */
66
+ tabSlug: string;
67
+ /**
68
+ * Plural browse label ("Pre-Orders", "Digital Codes"). Used for tab bars
69
+ * and page headings, where `typeLabel`'s singular reads wrong.
70
+ */
71
+ pluralLabel: string;
72
+ /** Short label for the dense type-chip row on /products and /admin/products. */
73
+ chipLabel: string;
74
+ /**
75
+ * Dedicated public browse page for this type, or `null` when it browses on
76
+ * `/products` (art and stickers — see CLAUDE.md's Listing Types Reference).
77
+ * A non-null value also drives the "full <type> filters →" link shown on
78
+ * /products when exactly this type is selected.
79
+ */
80
+ browseRoute: string | null;
81
+ /** Which "Show X" default this type's browse surfaces apply. */
82
+ hideDefault: ListingHideDefault;
83
+ /** Sort set offered on admin/seller dashboards for this type. */
84
+ sortOptions: readonly SortOption[];
85
+ /** Narrower sort set offered on public browse surfaces for this type. */
86
+ publicSortOptions: readonly SortOption[];
87
+ /**
88
+ * `TABLE_KEYS` values for facets that only make sense for this type
89
+ * (auction bid range, classified meetup city, live-item species, …). The
90
+ * shared product facets (category/brand/price/condition) are implicit.
91
+ */
92
+ extraFacetKeys: readonly string[];
30
93
  }
31
94
  export declare const LISTING_TYPE_REGISTRY: Record<ListingType, ListingTypePlugin>;
32
95
  export declare function pluginFor(type: ListingType): ListingTypePlugin;
@@ -37,4 +100,28 @@ export declare function pluginFor(type: ListingType): ListingTypePlugin;
37
100
  * explicit `listingType` field. Falls back to "standard" when no prefix matches.
38
101
  */
39
102
  export declare function detectListingTypeFromSlug(slug: string): ListingType;
103
+ /**
104
+ * Sort options for a listing type. Replaces the hand-written
105
+ * `SORT_OPTIONS_BY_LISTING_TYPE` that used to live in
106
+ * `features/products/constants/sieve.ts`, which was missing five of the nine
107
+ * types and still carried a `bundle` key that stopped being a listingType in
108
+ * SB-UNI-D.
109
+ */
110
+ export declare function sortOptionsFor(type: ListingType, variant?: "admin" | "public"): readonly SortOption[];
111
+ /**
112
+ * Sort options common to EVERY type in `types` — what a multi-type selection
113
+ * (or the unfiltered "all types" view) can safely offer, since a sort field
114
+ * only valid for one type would silently no-op (or trip FAILED_PRECONDITION)
115
+ * on the others.
116
+ *
117
+ * With a single type this returns that type's own set, so the caller doesn't
118
+ * need to special-case "exactly one selected".
119
+ */
120
+ export declare function commonSortOptionsFor(types: readonly ListingType[], variant?: "admin" | "public"): readonly SortOption[];
121
+ /**
122
+ * Which "Show X" quick-filter applies to a set of listing types. A mixed
123
+ * selection can need more than one toggle (auctions end, products sell out),
124
+ * so this returns every distinct default across the set.
125
+ */
126
+ export declare function hideDefaultsFor(types: readonly ListingType[]): ListingHideDefault[];
40
127
  export { LISTING_TYPE_CAPABILITIES };
@@ -4,9 +4,22 @@
4
4
  * Adding a new listing type later means:
5
5
  * 1. Add a folder `<type>/{config,schema,ctas,og,seed-factory}.ts`
6
6
  * 2. Add a row to `LISTING_TYPE_CAPABILITIES` in `./capabilities.ts`
7
- * 3. Add the import + entry below
7
+ * 3. Add a row to `ALL_LISTING_TYPES_MAP` in `./feature-flags.ts`
8
+ * 4. Add the import + entry below
8
9
  *
9
10
  * No grep-the-codebase sweep required. Future-expansion Pattern 3.
11
+ *
12
+ * BROWSE CHROME (2026-08-21) — the plugin also carries the tab/sort/filter
13
+ * metadata every listing surface needs, so tab bars, chip groups, sort
14
+ * dropdowns and filter drawers are DERIVED from this one map instead of
15
+ * hand-copied. Before this, at least nine independent "list every listing
16
+ * type" arrays existed (tab constants, admin type-filter maps, the seller
17
+ * TypeDropdown, useListingTypeFlags, SORT_OPTIONS_BY_LISTING_TYPE, …) and
18
+ * they had silently drifted: `art` and `stickers` were missing from most of
19
+ * them, `bundle` — which stopped being a listingType in SB-UNI-D — was still
20
+ * present in others, and the public /products chips offered only 4 of 9
21
+ * types. `scripts/audit-listing-type-tab-coverage.mjs` now blocks any array
22
+ * that doesn't cover the full union.
10
23
  */
11
24
  import * as standard from "./standard/config";
12
25
  import * as auction from "./auction/config";
@@ -50,6 +63,55 @@ export function detectListingTypeFromSlug(slug) {
50
63
  }
51
64
  return "standard";
52
65
  }
66
+ // ---------------------------------------------------------------------------
67
+ // Derived browse-chrome lookups
68
+ // ---------------------------------------------------------------------------
69
+ //
70
+ // Everything below is COMPUTED from LISTING_TYPE_REGISTRY. Never hand-write a
71
+ // parallel map — that is the exact drift this section exists to end.
72
+ /**
73
+ * Sort options for a listing type. Replaces the hand-written
74
+ * `SORT_OPTIONS_BY_LISTING_TYPE` that used to live in
75
+ * `features/products/constants/sieve.ts`, which was missing five of the nine
76
+ * types and still carried a `bundle` key that stopped being a listingType in
77
+ * SB-UNI-D.
78
+ */
79
+ export function sortOptionsFor(type, variant = "admin") {
80
+ const plugin = LISTING_TYPE_REGISTRY[type];
81
+ return variant === "public" ? plugin.publicSortOptions : plugin.sortOptions;
82
+ }
83
+ /**
84
+ * Sort options common to EVERY type in `types` — what a multi-type selection
85
+ * (or the unfiltered "all types" view) can safely offer, since a sort field
86
+ * only valid for one type would silently no-op (or trip FAILED_PRECONDITION)
87
+ * on the others.
88
+ *
89
+ * With a single type this returns that type's own set, so the caller doesn't
90
+ * need to special-case "exactly one selected".
91
+ */
92
+ export function commonSortOptionsFor(types, variant = "admin") {
93
+ if (types.length === 0)
94
+ return sortOptionsFor("standard", variant);
95
+ if (types.length === 1)
96
+ return sortOptionsFor(types[0], variant);
97
+ const [first, ...rest] = types;
98
+ const restSets = rest.map((t) => new Set(sortOptionsFor(t, variant).map((o) => o.value)));
99
+ const shared = sortOptionsFor(first, variant).filter((option) => restSets.every((set) => set.has(option.value)));
100
+ // Every type derives from BASE_SORT_OPTIONS, so the intersection is never
101
+ // empty in practice — but fall back rather than render a sortless toolbar.
102
+ return shared.length > 0 ? shared : sortOptionsFor("standard", variant);
103
+ }
104
+ /**
105
+ * Which "Show X" quick-filter applies to a set of listing types. A mixed
106
+ * selection can need more than one toggle (auctions end, products sell out),
107
+ * so this returns every distinct default across the set.
108
+ */
109
+ export function hideDefaultsFor(types) {
110
+ const seen = new Set();
111
+ for (const type of types)
112
+ seen.add(LISTING_TYPE_REGISTRY[type].hideDefault);
113
+ return [...seen];
114
+ }
53
115
  // Re-export the capability map so consumers can pull both surfaces from
54
116
  // the same module path.
55
117
  export { LISTING_TYPE_CAPABILITIES };
@@ -12,4 +12,63 @@ export declare const config: {
12
12
  priceLabel: string;
13
13
  typeLabel: string;
14
14
  showsStockQuantity: boolean;
15
+ tabSlug: string;
16
+ pluralLabel: string;
17
+ chipLabel: string;
18
+ browseRoute: string;
19
+ hideDefault: "sold";
20
+ sortOptions: readonly [{
21
+ readonly value: string;
22
+ readonly label: "Newest First";
23
+ }, {
24
+ readonly value: string;
25
+ readonly label: "Oldest First";
26
+ }, {
27
+ readonly value: string;
28
+ readonly label: "Price: Low to High";
29
+ }, {
30
+ readonly value: string;
31
+ readonly label: "Price: High to Low";
32
+ }, {
33
+ readonly value: string;
34
+ readonly label: "Name: A–Z";
35
+ }, {
36
+ readonly value: string;
37
+ readonly label: "Name: Z–A";
38
+ }, {
39
+ readonly value: string;
40
+ readonly label: "Featured First";
41
+ }, {
42
+ readonly value: string;
43
+ readonly label: "Promoted First";
44
+ }, {
45
+ readonly value: string;
46
+ readonly label: "Recently Updated";
47
+ }, {
48
+ readonly value: string;
49
+ readonly label: "Most Viewed";
50
+ }];
51
+ publicSortOptions: readonly [{
52
+ readonly value: string;
53
+ readonly label: "Newest First";
54
+ }, {
55
+ readonly value: string;
56
+ readonly label: "Oldest First";
57
+ }, {
58
+ readonly value: string;
59
+ readonly label: "Price: Low to High";
60
+ }, {
61
+ readonly value: string;
62
+ readonly label: "Price: High to Low";
63
+ }, {
64
+ readonly value: string;
65
+ readonly label: "Name: A–Z";
66
+ }, {
67
+ readonly value: string;
68
+ readonly label: "Name: Z–A";
69
+ }, {
70
+ readonly value: string;
71
+ readonly label: "Most Viewed";
72
+ }];
73
+ extraFacetKeys: readonly string[];
15
74
  };
@@ -1,5 +1,6 @@
1
1
  import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
2
2
  import { ROUTES } from "../../../../next/routing/route-map";
3
+ import { STANDARD_SORT_OPTIONS, STANDARD_PUBLIC_SORT_OPTIONS, } from "../../../../features/products/constants/sieve";
3
4
  export const LISTING_TYPE = "art";
4
5
  export const capability = LISTING_TYPE_CAPABILITIES.art;
5
6
  export const config = {
@@ -11,4 +12,15 @@ export const config = {
11
12
  priceLabel: "Price (₹)",
12
13
  typeLabel: "Art Print",
13
14
  showsStockQuantity: true,
15
+ tabSlug: "art",
16
+ pluralLabel: "Art",
17
+ chipLabel: "Art",
18
+ // `/art` is a COMBINED browse page spanning art + stickers, and art
19
+ // detail pages use the standard product route — so this is a real
20
+ // dedicated browse surface even though detailRoute points at /products.
21
+ browseRoute: String(ROUTES.PUBLIC.ART),
22
+ hideDefault: "sold",
23
+ sortOptions: STANDARD_SORT_OPTIONS,
24
+ publicSortOptions: STANDARD_PUBLIC_SORT_OPTIONS,
25
+ extraFacetKeys: [],
14
26
  };
@@ -12,4 +12,57 @@ export declare const config: {
12
12
  priceLabel: string;
13
13
  typeLabel: string;
14
14
  showsStockQuantity: boolean;
15
+ tabSlug: string;
16
+ pluralLabel: string;
17
+ chipLabel: string;
18
+ browseRoute: string;
19
+ hideDefault: "ended";
20
+ sortOptions: readonly [{
21
+ readonly value: string;
22
+ readonly label: "Ending Soon";
23
+ }, {
24
+ readonly value: string;
25
+ readonly label: "Just Started";
26
+ }, {
27
+ readonly value: string;
28
+ readonly label: "Lowest Current Bid";
29
+ }, {
30
+ readonly value: string;
31
+ readonly label: "Highest Current Bid";
32
+ }, {
33
+ readonly value: string;
34
+ readonly label: "Lowest Starting Bid";
35
+ }, {
36
+ readonly value: string;
37
+ readonly label: "Most Bids";
38
+ }, {
39
+ readonly value: string;
40
+ readonly label: "Fewest Bids";
41
+ }, {
42
+ readonly value: string;
43
+ readonly label: "Buy It Now: Low–High";
44
+ }, {
45
+ readonly value: string;
46
+ readonly label: "Oldest Listed";
47
+ }];
48
+ publicSortOptions: readonly [{
49
+ readonly value: string;
50
+ readonly label: "Ending Soon";
51
+ }, {
52
+ readonly value: string;
53
+ readonly label: "Just Started";
54
+ }, {
55
+ readonly value: string;
56
+ readonly label: "Lowest Current Bid";
57
+ }, {
58
+ readonly value: string;
59
+ readonly label: "Highest Current Bid";
60
+ }, {
61
+ readonly value: string;
62
+ readonly label: "Most Bids";
63
+ }, {
64
+ readonly value: string;
65
+ readonly label: "Buy It Now: Low–High";
66
+ }];
67
+ extraFacetKeys: readonly string[];
15
68
  };
@@ -1,5 +1,7 @@
1
1
  import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
2
2
  import { ROUTES } from "../../../../next/routing/route-map";
3
+ import { TABLE_KEYS } from "../../../../constants/table-keys";
4
+ import { AUCTION_SORT_OPTIONS, AUCTION_PUBLIC_SORT_OPTIONS, } from "../../../../features/products/constants/sieve";
3
5
  export const LISTING_TYPE = "auction";
4
6
  export const capability = LISTING_TYPE_CAPABILITIES.auction;
5
7
  export const config = {
@@ -11,4 +13,19 @@ export const config = {
11
13
  priceLabel: "Suggested Retail Price (₹)",
12
14
  typeLabel: "Auction",
13
15
  showsStockQuantity: false,
16
+ tabSlug: "auctions",
17
+ pluralLabel: "Auctions",
18
+ chipLabel: "Auctions",
19
+ browseRoute: String(ROUTES.PUBLIC.AUCTIONS),
20
+ // An auction is never "sold out" — it ends. Hiding by stock would hide
21
+ // every live auction, since auctions don't carry meaningful stock.
22
+ hideDefault: "ended",
23
+ sortOptions: AUCTION_SORT_OPTIONS,
24
+ publicSortOptions: AUCTION_PUBLIC_SORT_OPTIONS,
25
+ extraFacetKeys: [
26
+ TABLE_KEYS.MIN_BID,
27
+ TABLE_KEYS.MAX_BID,
28
+ TABLE_KEYS.DATE_FROM,
29
+ TABLE_KEYS.DATE_TO,
30
+ ],
14
31
  };
@@ -12,4 +12,63 @@ export declare const config: {
12
12
  priceLabel: string;
13
13
  typeLabel: string;
14
14
  showsStockQuantity: boolean;
15
+ tabSlug: string;
16
+ pluralLabel: string;
17
+ chipLabel: string;
18
+ browseRoute: string;
19
+ hideDefault: "sold";
20
+ sortOptions: readonly [{
21
+ readonly value: string;
22
+ readonly label: "Newest First";
23
+ }, {
24
+ readonly value: string;
25
+ readonly label: "Oldest First";
26
+ }, {
27
+ readonly value: string;
28
+ readonly label: "Price: Low to High";
29
+ }, {
30
+ readonly value: string;
31
+ readonly label: "Price: High to Low";
32
+ }, {
33
+ readonly value: string;
34
+ readonly label: "Name: A–Z";
35
+ }, {
36
+ readonly value: string;
37
+ readonly label: "Name: Z–A";
38
+ }, {
39
+ readonly value: string;
40
+ readonly label: "Featured First";
41
+ }, {
42
+ readonly value: string;
43
+ readonly label: "Promoted First";
44
+ }, {
45
+ readonly value: string;
46
+ readonly label: "Recently Updated";
47
+ }, {
48
+ readonly value: string;
49
+ readonly label: "Most Viewed";
50
+ }];
51
+ publicSortOptions: readonly [{
52
+ readonly value: string;
53
+ readonly label: "Newest First";
54
+ }, {
55
+ readonly value: string;
56
+ readonly label: "Oldest First";
57
+ }, {
58
+ readonly value: string;
59
+ readonly label: "Price: Low to High";
60
+ }, {
61
+ readonly value: string;
62
+ readonly label: "Price: High to Low";
63
+ }, {
64
+ readonly value: string;
65
+ readonly label: "Name: A–Z";
66
+ }, {
67
+ readonly value: string;
68
+ readonly label: "Name: Z–A";
69
+ }, {
70
+ readonly value: string;
71
+ readonly label: "Most Viewed";
72
+ }];
73
+ extraFacetKeys: readonly string[];
15
74
  };
@@ -1,5 +1,7 @@
1
1
  import { LISTING_TYPE_CAPABILITIES } from "../capabilities";
2
2
  import { ROUTES } from "../../../../next/routing/route-map";
3
+ import { TABLE_KEYS } from "../../../../constants/table-keys";
4
+ import { STANDARD_SORT_OPTIONS, STANDARD_PUBLIC_SORT_OPTIONS, } from "../../../../features/products/constants/sieve";
3
5
  export const LISTING_TYPE = "classified";
4
6
  export const capability = LISTING_TYPE_CAPABILITIES.classified;
5
7
  export const config = {
@@ -11,4 +13,16 @@ export const config = {
11
13
  priceLabel: "Asking Price (₹)",
12
14
  typeLabel: "Classified",
13
15
  showsStockQuantity: true,
16
+ tabSlug: "classifieds",
17
+ pluralLabel: "Classifieds",
18
+ chipLabel: "Classifieds",
19
+ browseRoute: String(ROUTES.PUBLIC.CLASSIFIED),
20
+ hideDefault: "sold",
21
+ sortOptions: STANDARD_SORT_OPTIONS,
22
+ publicSortOptions: STANDARD_PUBLIC_SORT_OPTIONS,
23
+ extraFacetKeys: [
24
+ TABLE_KEYS.CITY,
25
+ TABLE_KEYS.ACCEPTS_SHIPPING,
26
+ TABLE_KEYS.NEGOTIABLE,
27
+ ],
14
28
  };
@@ -12,4 +12,63 @@ export declare const config: {
12
12
  priceLabel: string;
13
13
  typeLabel: string;
14
14
  showsStockQuantity: boolean;
15
+ tabSlug: string;
16
+ pluralLabel: string;
17
+ chipLabel: string;
18
+ browseRoute: string;
19
+ hideDefault: "sold";
20
+ sortOptions: readonly [{
21
+ readonly value: string;
22
+ readonly label: "Newest First";
23
+ }, {
24
+ readonly value: string;
25
+ readonly label: "Oldest First";
26
+ }, {
27
+ readonly value: string;
28
+ readonly label: "Price: Low to High";
29
+ }, {
30
+ readonly value: string;
31
+ readonly label: "Price: High to Low";
32
+ }, {
33
+ readonly value: string;
34
+ readonly label: "Name: A–Z";
35
+ }, {
36
+ readonly value: string;
37
+ readonly label: "Name: Z–A";
38
+ }, {
39
+ readonly value: string;
40
+ readonly label: "Featured First";
41
+ }, {
42
+ readonly value: string;
43
+ readonly label: "Promoted First";
44
+ }, {
45
+ readonly value: string;
46
+ readonly label: "Recently Updated";
47
+ }, {
48
+ readonly value: string;
49
+ readonly label: "Most Viewed";
50
+ }];
51
+ publicSortOptions: readonly [{
52
+ readonly value: string;
53
+ readonly label: "Newest First";
54
+ }, {
55
+ readonly value: string;
56
+ readonly label: "Oldest First";
57
+ }, {
58
+ readonly value: string;
59
+ readonly label: "Price: Low to High";
60
+ }, {
61
+ readonly value: string;
62
+ readonly label: "Price: High to Low";
63
+ }, {
64
+ readonly value: string;
65
+ readonly label: "Name: A–Z";
66
+ }, {
67
+ readonly value: string;
68
+ readonly label: "Name: Z–A";
69
+ }, {
70
+ readonly value: string;
71
+ readonly label: "Most Viewed";
72
+ }];
73
+ extraFacetKeys: readonly string[];
15
74
  };