@mohasinac/appkit 3.8.2 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +4 -4
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +8 -8
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +1 -1
- package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +2 -2
- package/dist/_internal/server/features/bundles/actions.js +2 -2
- package/dist/_internal/server/features/bundles/og.d.ts +1 -1
- package/dist/_internal/server/features/bundles/og.js +4 -5
- package/dist/_internal/server/features/checkout/actions.js +57 -21
- package/dist/_internal/server/features/checkout/stock-restore.d.ts +19 -0
- package/dist/_internal/server/features/checkout/stock-restore.js +80 -0
- package/dist/_internal/server/features/checkout/upi-resolution.d.ts +11 -0
- package/dist/_internal/server/features/checkout/upi-resolution.js +28 -0
- package/dist/_internal/server/features/classified/og.js +1 -1
- package/dist/_internal/server/features/digital-code/og.js +1 -1
- package/dist/_internal/server/features/item-requests/og.d.ts +2 -2
- package/dist/_internal/server/features/item-requests/og.js +4 -5
- package/dist/_internal/server/features/live/og.js +1 -1
- package/dist/_internal/server/features/lottery/adapters.d.ts +2 -2
- package/dist/_internal/server/features/lottery/adapters.js +1 -1
- package/dist/_internal/server/features/orders/actions.d.ts +28 -0
- package/dist/_internal/server/features/orders/actions.js +239 -4
- package/dist/_internal/server/features/orders/adapters.js +3 -0
- package/dist/_internal/server/features/payments/data.js +3 -2
- package/dist/_internal/server/features/payouts/actions.d.ts +2 -2
- package/dist/_internal/server/features/payouts/actions.js +4 -3
- package/dist/_internal/server/features/pre-orders/service.d.ts +1 -1
- package/dist/_internal/server/features/pre-orders/service.js +3 -2
- package/dist/_internal/server/features/prize-draws/og.js +5 -5
- package/dist/_internal/server/features/products/og.js +1 -1
- package/dist/_internal/server/features/promotions/service.js +3 -1
- package/dist/_internal/server/features/refunds/actions.d.ts +2 -2
- package/dist/_internal/server/features/refunds/actions.js +7 -6
- package/dist/_internal/server/functions/firestore.js +1 -1
- package/dist/_internal/server/functions/scheduled.d.ts +4 -1
- package/dist/_internal/server/functions/scheduled.js +26 -2
- package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +1 -1
- package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +4 -0
- package/dist/_internal/server/jobs/core/hardBanCascade.js +15 -4
- package/dist/_internal/server/jobs/core/hardBanReinstatement.d.ts +16 -0
- package/dist/_internal/server/jobs/core/hardBanReinstatement.js +63 -0
- package/dist/_internal/server/jobs/core/jobRunners.js +3 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +1 -1
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +10 -0
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +60 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.d.ts +15 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +59 -0
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.d.ts +7 -0
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +32 -6
- package/dist/_internal/server/jobs/handlers/hardBanReinstatement.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/hardBanReinstatement.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +3 -0
- package/dist/_internal/server/jobs/handlers/index.js +3 -0
- package/dist/_internal/server/jobs/handlers/messages.d.ts +4 -0
- package/dist/_internal/server/jobs/handlers/messages.js +4 -0
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +3 -3
- package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +12 -12
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +1 -1
- package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +5 -5
- package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.js +2 -0
- package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.js +2 -0
- package/dist/_internal/shared/actions/action-registry.js +27 -0
- package/dist/_internal/shared/checkout/order-math.js +3 -2
- package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
- package/dist/_internal/shared/checkout/rules/preorder.rule.js +7 -0
- package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +7 -0
- package/dist/_internal/shared/checkout/rules/types.d.ts +11 -0
- package/dist/_internal/shared/features/auctions/errors.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +0 -1
- package/dist/_internal/shared/features/categories/bundle-copy.js +0 -1
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +6 -6
- package/dist/_internal/shared/features/categories/bundle-schemas.js +2 -2
- package/dist/_internal/shared/features/checkout/config.d.ts +3 -3
- package/dist/_internal/shared/features/checkout/config.js +3 -3
- package/dist/_internal/shared/features/emi/schedule.d.ts +6 -6
- package/dist/_internal/shared/features/emi/schedule.js +10 -9
- package/dist/_internal/shared/features/promotions/errors.js +1 -1
- package/dist/_internal/shared/fees/calculator.d.ts +5 -5
- package/dist/_internal/shared/fees/calculator.js +19 -19
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/constants/api-endpoints.d.ts +9 -0
- package/dist/constants/api-endpoints.js +3 -0
- package/dist/constants/field-names.d.ts +4 -0
- package/dist/constants/field-names.js +4 -0
- package/dist/features/admin/components/AdminArtView.js +2 -2
- package/dist/features/admin/components/AdminBidsView.js +2 -2
- package/dist/features/admin/components/AdminBundleEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminBundleEditorView.js +8 -8
- package/dist/features/admin/components/AdminBundlesView.js +6 -6
- package/dist/features/admin/components/AdminClassifiedView.js +2 -2
- package/dist/features/admin/components/AdminDigitalCodesView.js +2 -2
- package/dist/features/admin/components/AdminLiveView.js +2 -2
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +6 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +45 -5
- package/dist/features/admin/components/AdminOrdersView.js +8 -3
- package/dist/features/admin/components/AdminPayoutsView.js +2 -2
- package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -2
- package/dist/features/admin/components/AdminReturnRequestsView.js +2 -2
- package/dist/features/admin/components/AdminSectionsView.js +4 -4
- package/dist/features/admin/components/AdminSiteSettingsView.js +11 -11
- package/dist/features/admin/components/AdminStickersView.js +2 -2
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
- package/dist/features/admin/components/sections/adminSectionsBuildParse.js +13 -5
- package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +9 -5
- package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +3 -2
- package/dist/features/admin/schemas/firestore.d.ts +9 -7
- package/dist/features/admin/schemas/firestore.js +4 -3
- package/dist/features/auctions/components/AuctionBidsTable.js +3 -3
- package/dist/features/auth/checkout-value-otp.d.ts +46 -0
- package/dist/features/auth/checkout-value-otp.js +73 -0
- package/dist/features/auth/repository/user.repository.d.ts +6 -0
- package/dist/features/auth/repository/user.repository.js +19 -0
- package/dist/features/auth/schemas/firestore.d.ts +10 -0
- package/dist/features/auth/schemas/firestore.js +2 -0
- package/dist/features/cart/actions/cart-actions.d.ts +1 -1
- package/dist/features/cart/actions/cart-actions.js +4 -4
- package/dist/features/cart/components/CartView.d.ts +2 -2
- package/dist/features/cart/components/ShippingPicker.d.ts +4 -4
- package/dist/features/cart/components/ShippingPicker.js +11 -11
- package/dist/features/cart/repository/cart.repository.d.ts +1 -1
- package/dist/features/cart/repository/cart.repository.js +2 -2
- package/dist/features/cart/schemas/firestore.d.ts +2 -2
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -3
- package/dist/features/catalogue/components/PublicCatalogueView.js +2 -2
- package/dist/features/catalogue/schemas/validation.js +1 -1
- package/dist/features/categories/components/BundleCollage.js +2 -2
- package/dist/features/categories/components/BundleDetailView.js +2 -2
- package/dist/features/categories/components/BundleItemsPicker.d.ts +1 -1
- package/dist/features/categories/components/BundleItemsPicker.js +2 -2
- package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/categories/schemas/index.d.ts +3 -3
- package/dist/features/categories/schemas/index.js +2 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +16 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +83 -0
- package/dist/features/checkout/actions/index.d.ts +1 -0
- package/dist/features/checkout/actions/index.js +1 -0
- package/dist/features/checkout/schemas/firestore.d.ts +1 -1
- package/dist/features/classified/components/index.d.ts +0 -4
- package/dist/features/classified/components/index.js +0 -2
- package/dist/features/digital-codes/components/index.d.ts +0 -4
- package/dist/features/digital-codes/components/index.js +0 -2
- package/dist/features/events/schemas/index.d.ts +1 -1
- package/dist/features/events/schemas/index.js +1 -1
- package/dist/features/homepage/components/BrandsSection.d.ts +4 -1
- package/dist/features/homepage/components/BrandsSection.js +2 -2
- package/dist/features/homepage/components/CustomCardsSection.js +3 -3
- package/dist/features/homepage/components/CustomerReviewsSection.d.ts +4 -1
- package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/EventsSection.d.ts +4 -1
- package/dist/features/homepage/components/EventsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedAuctionsSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedAuctionsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -2
- package/dist/features/homepage/components/FeaturedPreOrdersSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedPreOrdersSection.js +2 -2
- package/dist/features/homepage/components/FeaturedProductsSection.d.ts +2 -1
- package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
- package/dist/features/homepage/components/FeaturedStoresSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedStoresSection.js +2 -2
- package/dist/features/homepage/components/HomepageCustomerReviewsSection.d.ts +4 -1
- package/dist/features/homepage/components/HomepageCustomerReviewsSection.js +2 -2
- package/dist/features/homepage/components/SectionCarousel.d.ts +3 -1
- package/dist/features/homepage/components/SectionCarousel.js +2 -2
- package/dist/features/homepage/components/ShopByCategorySection.d.ts +4 -1
- package/dist/features/homepage/components/ShopByCategorySection.js +2 -2
- package/dist/features/homepage/lib/section-renderer.js +9 -9
- package/dist/features/homepage/schemas/firestore.d.ts +8 -0
- package/dist/features/live/components/index.d.ts +0 -4
- package/dist/features/live/components/index.js +0 -2
- package/dist/features/lottery/types/index.d.ts +3 -3
- package/dist/features/lottery/types/index.js +5 -5
- package/dist/features/orders/components/OrderPaymentSummary.js +2 -2
- package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
- package/dist/features/orders/components/RefundHistoryTable.js +1 -1
- package/dist/features/orders/components/RefundRequestView.js +1 -1
- package/dist/features/orders/constants/payment-window.d.ts +10 -0
- package/dist/features/orders/constants/payment-window.js +10 -0
- package/dist/features/orders/repository/orders.repository.d.ts +25 -0
- package/dist/features/orders/repository/orders.repository.js +50 -1
- package/dist/features/orders/schemas/firestore.d.ts +50 -2
- package/dist/features/orders/schemas/index.d.ts +24 -24
- package/dist/features/orders/schemas/index.js +20 -20
- package/dist/features/orders/types/index.d.ts +4 -0
- package/dist/features/orders/utils/bundle-grouping.d.ts +1 -1
- package/dist/features/orders/utils/bundle-grouping.js +1 -1
- package/dist/features/payments/schemas/index.d.ts +10 -10
- package/dist/features/payments/schemas/index.js +9 -9
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
- package/dist/features/products/components/ArtStickersListView.d.ts +7 -0
- package/dist/features/products/components/ArtStickersListView.js +57 -0
- package/dist/features/products/components/GroupSettingsPanel.js +1 -1
- package/dist/features/products/components/MakeOfferButton.js +3 -3
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
- package/dist/features/products/components/PrizeDrawCollage.js +2 -2
- package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
- package/dist/features/products/components/PrizeRevealModal.js +1 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -9
- package/dist/features/products/components/ProductForm.js +2 -2
- package/dist/features/products/components/ProductGrid.js +2 -2
- package/dist/features/products/components/ProductsIndexListing.d.ts +13 -1
- package/dist/features/products/components/ProductsIndexListing.js +7 -5
- package/dist/features/products/components/ProductsIndexPageView.js +6 -1
- package/dist/features/products/constants/listing-tabs.d.ts +42 -17
- package/dist/features/products/constants/listing-tabs.js +25 -6
- package/dist/features/products/schemas/catalog-product.d.ts +5 -5
- package/dist/features/products/schemas/catalog-product.js +1 -1
- package/dist/features/products/schemas/firestore.d.ts +5 -5
- package/dist/features/products/schemas/firestore.js +2 -2
- package/dist/features/products/types/index.d.ts +5 -2
- package/dist/features/promotions/components/CouponCard.js +2 -2
- package/dist/features/promotions/schemas/firestore.d.ts +2 -0
- package/dist/features/promotions/schemas/firestore.js +1 -0
- package/dist/features/promotions/schemas/index.d.ts +14 -14
- package/dist/features/promotions/schemas/index.js +6 -6
- package/dist/features/scams/components/ScamProfileView.js +3 -7
- package/dist/features/scams/components/ScamRegistryView.js +2 -6
- package/dist/features/scams/schemas/firestore.d.ts +1 -1
- package/dist/features/search/components/Search.d.ts +1 -1
- package/dist/features/seller/actions/offer-actions.js +1 -1
- package/dist/features/seller/components/PrintCenterView.js +2 -2
- package/dist/features/seller/components/QuickProductForm.js +5 -5
- package/dist/features/seller/components/SellerArtView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +2 -2
- package/dist/features/seller/components/SellerBidsView.js +2 -2
- package/dist/features/seller/components/SellerBundlesView.js +6 -6
- package/dist/features/seller/components/SellerClassifiedView.js +2 -2
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerLiveView.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +2 -2
- package/dist/features/seller/components/SellerOrdersView.js +3 -3
- package/dist/features/seller/components/SellerPayoutRequestView.js +2 -2
- package/dist/features/seller/components/SellerPayoutSettingsView.js +2 -2
- package/dist/features/seller/components/SellerPayoutsView.js +2 -2
- package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
- package/dist/features/seller/components/SellerProductShell.js +8 -8
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +6 -6
- package/dist/features/seller/components/SellerStickersView.js +2 -2
- package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
- package/dist/features/seller/hooks/useSellerListingData.js +3 -2
- package/dist/features/shipments/components/AdminShipmentEditorView.js +10 -10
- package/dist/features/shipments/components/AdminShipmentLotItemsView.js +4 -4
- package/dist/features/shipments/components/AdminShipmentProjectionsView.js +5 -5
- package/dist/features/shipments/components/AdminShipmentsView.js +4 -4
- package/dist/features/shipments/repository/shipment-lots.repository.d.ts +2 -2
- package/dist/features/shipments/repository/shipment-lots.repository.js +8 -8
- package/dist/features/shipments/schemas/firestore.d.ts +21 -21
- package/dist/features/shipments/schemas/firestore.js +9 -9
- package/dist/features/shipments/schemas/validation.d.ts +30 -30
- package/dist/features/shipments/schemas/validation.js +6 -6
- package/dist/features/shipments/utils/cost-allocation.d.ts +5 -5
- package/dist/features/shipments/utils/cost-allocation.js +39 -38
- package/dist/features/store-extensions/schemas/firestore.d.ts +5 -5
- package/dist/features/stores/components/StoreDetailLayoutView.js +9 -13
- package/dist/features/stores/schemas/firestore.d.ts +7 -7
- package/dist/features/stores/schemas/index.d.ts +84 -84
- package/dist/features/stores/schemas/index.js +5 -5
- package/dist/features/tester/seed-data/categories-tester-seed-data.js +1 -1
- package/dist/features/tester/seed-data/products-tester-seed-data.js +6 -6
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +9 -2
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +8 -1
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +13 -2
- package/dist/features/whatsapp-bot/types/index.d.ts +9 -1
- package/dist/index.d.ts +3 -7
- package/dist/index.js +7 -5
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +6 -0
- package/dist/schemas/firestore-helpers.d.ts +2 -2
- package/dist/schemas/firestore-helpers.js +2 -2
- package/dist/schemas/registry.d.ts +73 -73
- package/dist/seed/bids-seed-data.js +6 -6
- package/dist/seed/blog-posts-seed-data.js +1 -0
- package/dist/seed/cart-seed-data.js +13 -13
- package/dist/seed/catalogue-seed-data.js +6 -6
- package/dist/seed/categories-seed-data.js +5 -5
- package/dist/seed/claimed-coupons-seed-data.js +3 -3
- package/dist/seed/coupons-seed-data.js +20 -20
- package/dist/seed/events-seed-data.js +27 -27
- package/dist/seed/factories/bid.factory.js +1 -1
- package/dist/seed/faq-seed-data.js +20 -1
- package/dist/seed/grouped-listings-seed-data.d.ts +2 -2
- package/dist/seed/grouped-listings-seed-data.js +3 -3
- package/dist/seed/homepage-sections-seed-data.js +10 -0
- package/dist/seed/offers-seed-data.js +19 -19
- package/dist/seed/orders-seed-data.js +29 -29
- package/dist/seed/payouts-seed-data.js +7 -7
- package/dist/seed/products-auctions-seed-data.js +6 -6
- package/dist/seed/products-preorders-seed-data.d.ts +2 -2
- package/dist/seed/products-preorders-seed-data.js +1 -1
- package/dist/seed/products-standard-seed-data.js +8 -8
- package/dist/seed/scammers-seed-data.js +2 -2
- package/dist/seed/shipments-seed-data.js +29 -29
- package/dist/seed/site-settings-seed-data.js +3 -2
- package/dist/seed/store-extensions-seed-data.js +8 -8
- package/dist/seed/stores-seed-data.js +37 -8
- package/dist/seed/users-seed-data.js +38 -1
- package/dist/server-entry.d.ts +1 -3
- package/dist/server-entry.js +1 -3
- package/dist/server.d.ts +2 -1
- package/dist/server.js +3 -1
- package/dist/ui/components/HorizontalScroller.js +3 -0
- package/dist/ui/components/PriceDisplay.js +3 -12
- package/dist/utils/number.formatter.d.ts +2 -7
- package/dist/utils/number.formatter.js +3 -8
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +8 -3
- package/dist/_internal/client/scaffolds/DashboardScaffold.d.ts +0 -34
- package/dist/_internal/client/scaffolds/DashboardScaffold.js +0 -26
- package/dist/_internal/client/theme/__tests__/ThemeProvider.test.d.ts +0 -1
- package/dist/_internal/client/theme/__tests__/ThemeProvider.test.js +0 -109
- package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +0 -1
- package/dist/_internal/server/features/auctions/__tests__/service.test.js +0 -140
- package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +0 -1
- package/dist/_internal/server/features/checkout/__tests__/actions.test.js +0 -600
- package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +0 -1
- package/dist/_internal/server/features/refunds/__tests__/actions.test.js +0 -263
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +0 -249
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +0 -65
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +0 -163
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +0 -115
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +0 -201
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +0 -169
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +0 -148
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +0 -210
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +0 -190
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +0 -161
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +0 -302
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +0 -96
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +0 -252
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +0 -1
- package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +0 -129
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +0 -15
- package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +0 -38
- package/dist/_internal/server/providers/index.d.ts +0 -11
- package/dist/_internal/server/providers/index.js +0 -11
- package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +0 -52
- package/dist/_internal/server/providers/payment/razorpay-mock.js +0 -118
- package/dist/_internal/server/providers/resolve.d.ts +0 -36
- package/dist/_internal/server/providers/resolve.js +0 -31
- package/dist/_internal/server/providers/shipping/shiprocket-mock.d.ts +0 -29
- package/dist/_internal/server/providers/shipping/shiprocket-mock.js +0 -152
- package/dist/_internal/shared/types/__tests__/action-result.test.d.ts +0 -1
- package/dist/_internal/shared/types/__tests__/action-result.test.js +0 -65
- package/dist/errors/__tests__/error-mapping.test.d.ts +0 -1
- package/dist/errors/__tests__/error-mapping.test.js +0 -122
- package/dist/errors/__tests__/safe-read.test.d.ts +0 -1
- package/dist/errors/__tests__/safe-read.test.js +0 -39
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +0 -1
- package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +0 -386
- package/dist/features/admin/components/AdminListingScaffold.d.ts +0 -41
- package/dist/features/admin/components/AdminListingScaffold.js +0 -68
- package/dist/features/admin/components/QuickActionsPanel.d.ts +0 -15
- package/dist/features/admin/components/QuickActionsPanel.js +0 -5
- package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +0 -1
- package/dist/features/admin/repository/__tests__/notification.repository.test.js +0 -356
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +0 -1
- package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +0 -298
- package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +0 -1
- package/dist/features/auctions/repository/__tests__/bid.repository.test.js +0 -290
- package/dist/features/auctions/repository/auctions.repository.d.ts +0 -12
- package/dist/features/auctions/repository/auctions.repository.js +0 -42
- package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/session.repository.test.js +0 -310
- package/dist/features/auth/repository/__tests__/session.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/session.test.js +0 -146
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +0 -171
- package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/sms-counter.test.js +0 -88
- package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/token.repository.test.js +0 -260
- package/dist/features/auth/repository/__tests__/token.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/token.test.js +0 -140
- package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/user.repository.test.js +0 -352
- package/dist/features/auth/repository/__tests__/user.test.d.ts +0 -1
- package/dist/features/auth/repository/__tests__/user.test.js +0 -226
- package/dist/features/before-after/repository/before-after.repository.d.ts +0 -13
- package/dist/features/before-after/repository/before-after.repository.js +0 -36
- package/dist/features/before-after/server.d.ts +0 -6
- package/dist/features/before-after/server.js +0 -6
- package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +0 -1
- package/dist/features/cart/repository/__tests__/cart.repository.test.js +0 -371
- package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +0 -1
- package/dist/features/categories/repository/__tests__/categories.repository.test.js +0 -813
- package/dist/features/collections/repository/collections.repository.d.ts +0 -8
- package/dist/features/collections/repository/collections.repository.js +0 -16
- package/dist/features/collections/server.d.ts +0 -6
- package/dist/features/collections/server.js +0 -6
- package/dist/features/events/repository/__tests__/event.repository.test.d.ts +0 -1
- package/dist/features/events/repository/__tests__/event.repository.test.js +0 -299
- package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +0 -1
- package/dist/features/faq/repository/__tests__/faqs.repository.test.js +0 -311
- package/dist/features/forms/Form.d.ts +0 -25
- package/dist/features/forms/Form.js +0 -37
- package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +0 -1
- package/dist/features/history/repository/__tests__/user-history.repository.test.js +0 -180
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +0 -1
- package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +0 -182
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +0 -1
- package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +0 -185
- package/dist/features/layout/ListingLayout.d.ts +0 -34
- package/dist/features/layout/ListingLayout.js +0 -103
- package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +0 -1
- package/dist/features/messages/repository/__tests__/conversations.repository.test.js +0 -257
- package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +0 -1
- package/dist/features/orders/repository/__tests__/orders.repository.test.js +0 -211
- package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +0 -1
- package/dist/features/payments/repository/__tests__/payout.repository.test.js +0 -292
- package/dist/features/pre-orders/repository/preorders.repository.d.ts +0 -8
- package/dist/features/pre-orders/repository/preorders.repository.js +0 -25
- package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +0 -1
- package/dist/features/products/repository/__tests__/product-features.repository.test.js +0 -329
- package/dist/features/products/repository/__tests__/products.repository.test.d.ts +0 -1
- package/dist/features/products/repository/__tests__/products.repository.test.js +0 -607
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +0 -1
- package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +0 -219
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +0 -1
- package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +0 -480
- package/dist/features/promotions/repository/promotions.repository.d.ts +0 -14
- package/dist/features/promotions/repository/promotions.repository.js +0 -43
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +0 -1
- package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +0 -327
- package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +0 -1
- package/dist/features/scams/repository/__tests__/scammer.repository.test.js +0 -385
- package/dist/features/search/repository/__tests__/search.repository.test.d.ts +0 -1
- package/dist/features/search/repository/__tests__/search.repository.test.js +0 -369
- package/dist/features/seller/components/SellerStatCard.d.ts +0 -14
- package/dist/features/seller/components/SellerStatCard.js +0 -6
- package/dist/features/seller/components/seller-products-styles.d.ts +0 -7
- package/dist/features/seller/components/seller-products-styles.js +0 -14
- package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +0 -1
- package/dist/features/seller/repository/__tests__/offer.repository.test.js +0 -458
- package/dist/features/seller/repository/seller.repository.d.ts +0 -22
- package/dist/features/seller/repository/seller.repository.js +0 -72
- package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.d.ts +0 -1
- package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.js +0 -37
- package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +0 -1
- package/dist/features/stores/repository/__tests__/store.repository.test.js +0 -261
- package/dist/features/stores/repository/stores.repository.d.ts +0 -11
- package/dist/features/stores/repository/stores.repository.js +0 -37
- package/dist/features/support/repository/__tests__/support.repository.test.d.ts +0 -1
- package/dist/features/support/repository/__tests__/support.repository.test.js +0 -312
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +0 -1
- package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +0 -139
- package/dist/features/wishlist/repository/wishlist.repository.d.ts +0 -13
- package/dist/features/wishlist/repository/wishlist.repository.js +0 -31
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +0 -1
- package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +0 -93
- package/dist/providers/shipping-shiprocket/index.d.ts +0 -297
- package/dist/providers/shipping-shiprocket/index.js +0 -194
- package/dist/providers/shipping-shiprocket/shiprocket-provider.d.ts +0 -45
- package/dist/providers/shipping-shiprocket/shiprocket-provider.js +0 -168
- package/dist/react/contexts/ThemeContext.d.ts +0 -13
- package/dist/react/contexts/ThemeContext.js +0 -64
- package/dist/schemas/webhooks/shiprocket.d.ts +0 -30
- package/dist/schemas/webhooks/shiprocket.js +0 -22
- package/dist/seed/actions/demo-seed-actions.d.ts +0 -42
- package/dist/seed/actions/demo-seed-actions.js +0 -36
- package/dist/seed/actions/index.d.ts +0 -1
- package/dist/seed/actions/index.js +0 -1
- package/dist/seed/sub-listings-seed-data.d.ts +0 -123
- package/dist/seed/sub-listings-seed-data.js +0 -447
- package/dist/seed/tester-checklist-seed-data.d.ts +0 -2
- package/dist/seed/tester-checklist-seed-data.js +0 -248
- package/dist/ui/components/DashboardStatsCard.d.ts +0 -15
- package/dist/ui/components/DashboardStatsCard.js +0 -27
- package/dist/ui/components/DashboardStatsCard.style.css +0 -68
- package/dist/ui/components/DynamicSelect.d.ts +0 -23
- package/dist/ui/components/DynamicSelect.js +0 -77
- package/dist/ui/components/DynamicSelect.style.css +0 -101
- package/dist/ui/components/InlineCreateSelect.d.ts +0 -48
- package/dist/ui/components/InlineCreateSelect.js +0 -75
- package/dist/ui/components/ListingViewShell.d.ts +0 -37
- package/dist/ui/components/ListingViewShell.js +0 -9
- package/dist/ui/components/PaginatedMultiSelect.d.ts +0 -28
- package/dist/ui/components/PaginatedMultiSelect.js +0 -141
- package/dist/ui/components/PaginatedMultiSelect.style.css +0 -272
- package/dist/ui/components/SectionTabs.d.ts +0 -19
- package/dist/ui/components/SectionTabs.js +0 -66
- package/dist/ui/components/SectionTabs.style.css +0 -164
- package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +0 -1
- package/dist/ui/components/__tests__/BulkActionBar.test.js +0 -96
- package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +0 -1
- package/dist/ui/components/__tests__/ListingToolbar.test.js +0 -125
- package/dist/ui/components/__tests__/new-primitives.test.d.ts +0 -1
- package/dist/ui/components/__tests__/new-primitives.test.js +0 -187
|
@@ -89,9 +89,9 @@ export function PrizeDrawItemsEditor({ items, onChange, onUploadImage, onUploadV
|
|
|
89
89
|
return (_jsxs(Stack, { gap: "md", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Heading, { level: 3, children: ["Prize Items (", items.length, ")"] }), _jsxs(Button, { type: "button", variant: "secondary", onClick: addItem, disabled: anyWon || items.length >= MAX_ITEMS, children: ["+ Add prize (", items.length, "/", MAX_ITEMS, ")"] })] }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Add between ", MIN_ITEMS, " and ", MAX_ITEMS, " prizes. Each entry will reveal exactly one of these. Items marked won during a prior reveal cannot be edited or removed."] }), anyWon ? (_jsxs(Div, { textSize: "sm", className: "border border-error/40", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "default", children: [_jsx(Span, { weight: "bold", children: "Draw locked." }), " At least one prize has been revealed \u2014 this listing can no longer be edited. To run a similar draw, clone it into a new prize-draw listing."] })) : warning ? (_jsx(Div, { className: CLS_WARN_BOX, children: warning })) : null, _jsx(Stack, { gap: "md", children: items.map((it, index) => {
|
|
90
90
|
const locked = it.isWon || anyWon;
|
|
91
91
|
return (_jsxs(Div, { className: `relative border border-[var(--appkit-color-border)] ${locked ? "opacity-60" : ""}`, rounded: "lg", padding: "md", children: [locked ? (_jsx(Row, { surface: "overlay-xs", className: "absolute inset-0 z-10 bg-[rgba(0,0,0,0.1)] dark: pointer-events-none", align: "center", justify: "center", rounded: "lg", children: _jsx(Text, { className: CLS_WON_BADGE, children: "Won \u2014 locked" }) })) : null, _jsxs(Row, { justify: "between", align: "center", className: "mb-3", children: [_jsxs(Heading, { level: 4, children: ["Prize #", it.itemNumber] }), _jsxs(Row, { gap: "xs", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, -1), disabled: locked || index === 0, "aria-label": "Move up", children: "\u2191" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(index, 1), disabled: locked || index === items.length - 1, "aria-label": "Move down", children: "\u2193" }), _jsx(Button, { type: "button", variant: "danger", size: "sm", onClick: () => removeItem(index), disabled: locked || items.length <= MIN_ITEMS, children: "Remove" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(FormField, { name: `item-${index}-title`, label: "Title", type: "text", value: it.title, onChange: (v) => update(index, { title: v }), disabled: locked, placeholder: "e.g. PSA 9 Charizard Base Set Holo" }), _jsx(FormField, { name: `item-${index}-description`, label: "Description (optional)", type: "textarea", value: it.description ?? "", onChange: (v) => update(index, { description: v }), disabled: locked, placeholder: "What makes this prize special?" }), _jsxs(Row, { gap: "md", children: [_jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-condition`, label: "Condition", type: "select", value: it.condition, onChange: (v) => update(index, { condition: v }), disabled: locked, options: CONDITION_OPTIONS }) }), _jsx(Div, { className: "flex-1", children: _jsx(FormField, { name: `item-${index}-value`, label: "Estimated value (\u20B9)", type: "number", value: it.estimatedValue != null
|
|
92
|
-
? String(
|
|
92
|
+
? String(it.estimatedValue)
|
|
93
93
|
: "", onChange: (v) => update(index, {
|
|
94
|
-
estimatedValue: Math.round((parseFloat(v) || 0) * 100),
|
|
94
|
+
estimatedValue: Math.round((parseFloat(v) || 0) * 100) / 100,
|
|
95
95
|
}), disabled: locked, placeholder: "2999" }) })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", weight: "medium", children: ["Images (", (it.images ?? []).length, "/", MAX_IMAGES_PER_ITEM, ")"] }), _jsx(Row, { gap: "sm", wrap: true, children: Array.from({ length: MAX_IMAGES_PER_ITEM }).map((_, slot) => {
|
|
96
96
|
const existing = (it.images ?? [])[slot];
|
|
97
97
|
return (_jsxs(Div, { className: "w-40", children: [_jsx(ImageUpload, { currentImage: existing, label: existing ? "Replace" : `Image ${slot + 1}`, onUpload: (file) => onUploadImage(file, it.itemNumber), onChange: (url) => setImage(index, slot, url) }), existing && !locked ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeImage(index, slot), children: "Remove" })) : null] }, slot));
|
|
@@ -155,6 +155,6 @@ export function PrizeRevealModal({ open, onClose, items, orderId, productId, onR
|
|
|
155
155
|
// audit-content-alignment-ok: theatrical reveal-modal centerpiece, not marketing content
|
|
156
156
|
_jsxs(Div, { className: `bg-[var(--appkit-color-surface-muted)] ${__P.p4} text-center`, rounded: "default", children: [_jsx(Text, { size: "lg", weight: "semibold", children: "Rolling\u2026" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "The winner was locked by the server before this animation started. Hang tight \u2014 we're just making it look pretty." })] })) : null, phase === "won" && winner ? (
|
|
157
157
|
// audit-content-alignment-ok: theatrical reveal-modal centerpiece, not marketing content
|
|
158
|
-
_jsxs(Div, { className: `border-2 border-[var(--appkit-color-primary)] bg-[var(--appkit-color-surface)] ${__P.p4} text-center`, rounded: "lg", children: [_jsx(Text, { className: "tracking-wider text-[var(--appkit-color-text-muted)]", size: "xs", transform: "uppercase", children: "You won" }), _jsxs(Heading, { level: 2, className: "my-2", children: ["#", winner.itemNumber, " \u2014 ", winner.title] }), winnerImg ? (_jsx(Div, { className: "relative mx-auto h-64 w-64 max-w-full", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: winnerImg, alt: winner.title, size: "hero", objectFit: "contain" }) })) : null, winner.estimatedValue != null ? (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Estimated value: \u20B9",
|
|
158
|
+
_jsxs(Div, { className: `border-2 border-[var(--appkit-color-primary)] bg-[var(--appkit-color-surface)] ${__P.p4} text-center`, rounded: "lg", children: [_jsx(Text, { className: "tracking-wider text-[var(--appkit-color-text-muted)]", size: "xs", transform: "uppercase", children: "You won" }), _jsxs(Heading, { level: 2, className: "my-2", children: ["#", winner.itemNumber, " \u2014 ", winner.title] }), winnerImg ? (_jsx(Div, { className: "relative mx-auto h-64 w-64 max-w-full", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: winnerImg, alt: winner.title, size: "hero", objectFit: "contain" }) })) : null, winner.estimatedValue != null ? (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Estimated value: \u20B9", winner.estimatedValue.toLocaleString("en-IN")] })) : null] })) : null, _jsxs(Div, { textSize: "xs", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-muted)] text-[var(--appkit-color-text-muted)]", padding: "inlineSm", rounded: "default", children: [_jsx(Span, { weight: "bold", children: "Fairness guarantee:" }), " ", "Winners are picked by ", _jsx("code", { children: "crypto.randomInt" }), " running on LetItRip's server before the animation starts. The animation is theatrical \u2014 neither the store nor LetItRip staff can influence the outcome.", " ", effectiveRngUrl ? (_jsx(Anchor, { href: effectiveRngUrl, tone: "none", underline: "always", children: "View RNG source code \u2192" })) : null] })] })] }));
|
|
159
159
|
}
|
|
160
160
|
export default PrizeRevealModal;
|
|
@@ -13,7 +13,6 @@ const CLS_STAR_EMPTY = "text-[var(--appkit-color-text-faint)] text-[length:var(-
|
|
|
13
13
|
const CLS_STOCK_IN = "bg-success-surface text-success dark:bg-success-surface dark:text-success";
|
|
14
14
|
const CLS_STOCK_OUT = "bg-error-surface text-error dark:bg-error-surface dark:text-error";
|
|
15
15
|
const CLS_BUNDLE_PILL = "inline-flex items-center gap-[var(--appkit-space-1)] rounded-full border border-success bg-success-surface px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-semibold text-success transition-colors hover:border-success hover:bg-success-surface dark:border-success/60 dark:bg-success-surface dark:text-success dark:hover:border-success dark:hover:bg-success-surface";
|
|
16
|
-
const CLS_DISCOUNT_BADGE = "rounded-full bg-error-surface px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-white";
|
|
17
16
|
const CLS_FREE_SHIPPING_ICON = "mt-0.5 flex-shrink-0 text-success";
|
|
18
17
|
const CLS_BUNDLE_BOX = "rounded-xl border border-success dark:border-success/60 bg-success-surface dark:bg-success-surface p-[var(--appkit-space-5)]";
|
|
19
18
|
const CLS_BUNDLE_ICON = "text-success dark:text-success";
|
|
@@ -23,9 +22,8 @@ const CLS_BUNDLE_LABEL = "text-[length:var(--appkit-text-xs)] text-success dark:
|
|
|
23
22
|
const CLS_BUNDLE_CTA = "flex-shrink-0 rounded-lg bg-success-surface hover:bg-success-surface px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-white transition-colors";
|
|
24
23
|
import { ROUTES } from "../../../next";
|
|
25
24
|
import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
26
|
-
import { Button, Container, Div, Heading, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Ol, Li, Dl, Dt, Dd, } from "../../../ui";
|
|
25
|
+
import { Button, Container, Div, Heading, Main, Nav, PriceDisplay, RichText, Row, Section, Span, Stack, Text, Ul, Ol, Li, Dl, Dt, Dd, } from "../../../ui";
|
|
27
26
|
import { normalizeRichTextHtml } from "../../../utils/string.formatter";
|
|
28
|
-
import { formatCurrency } from "../../../utils/number.formatter";
|
|
29
27
|
import { safeDisplayName } from "../../../security";
|
|
30
28
|
import { ReviewsList } from "../../reviews/components/ReviewsList";
|
|
31
29
|
import { ProductDetailView } from "./ProductDetailView";
|
|
@@ -122,9 +120,6 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
|
|
|
122
120
|
const title = String(p.title ?? p.name ?? "");
|
|
123
121
|
const price = typeof p.price === "number" ? p.price : null;
|
|
124
122
|
const originalPrice = typeof p.originalPrice === "number" ? p.originalPrice : null;
|
|
125
|
-
const discount = price && originalPrice && originalPrice > price
|
|
126
|
-
? Math.round(((originalPrice - price) / originalPrice) * 100)
|
|
127
|
-
: null;
|
|
128
123
|
const images = Array.isArray(p.images)
|
|
129
124
|
? p.images
|
|
130
125
|
: typeof p.mainImage === "string"
|
|
@@ -242,8 +237,6 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
|
|
|
242
237
|
})
|
|
243
238
|
.slice(0, 8)
|
|
244
239
|
.map(toProductItem);
|
|
245
|
-
const formattedPrice = price !== null ? formatCurrency(price, currency) : null;
|
|
246
|
-
const formattedOriginal = originalPrice !== null ? formatCurrency(originalPrice, currency) : null;
|
|
247
240
|
return (_jsxs(Main, { children: [_jsx(HistoryTracker, { productId: product.id, productType: "product", snapshot: {
|
|
248
241
|
title: product.title,
|
|
249
242
|
thumb: product.mainImage ?? product.images?.[0],
|
|
@@ -279,7 +272,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
|
|
|
279
272
|
categoryProductCount: (n, cat) => `${n} in ${cat}`,
|
|
280
273
|
} }), productFeatures && features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures })), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this product" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => (_jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller }), typeof p.storeRating === "number" && p.storeRating > 0 && (_jsx(Row, { gap: "xs", align: "center", className: "mt-0.5", children: _jsxs(Text, { size: "xs", color: "muted", children: [_jsx(Span, { className: "text-warning", "aria-hidden": "true", children: "\u2605" }), " ", p.storeRating.toFixed(1), typeof p.storeReviewCount === "number" &&
|
|
281
274
|
p.storeReviewCount > 0 &&
|
|
282
|
-
` · ${p.storeReviewCount} reviews`] }) }))] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [
|
|
275
|
+
` · ${p.storeReviewCount} reviews`] }) }))] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [price !== null && (_jsxs(Div, { children: [_jsx(PriceDisplay, { amount: price, originalAmount: originalPrice ?? undefined, currency: currency, variant: "detail" }), inStock && effectiveStock !== null && effectiveStock <= 10 && (_jsxs(Text, { className: "mt-1 text-warning", size: "xs", children: ["Only ", effectiveStock, " left \u2014 order soon!"] }))] })), _jsxs(Stack, { gap: "sm", children: [renderPrimaryActions ? (renderPrimaryActions({
|
|
283
276
|
productId: product.id,
|
|
284
277
|
productSlug: product.slug ?? slug,
|
|
285
278
|
productTitle: product.title,
|
|
@@ -162,9 +162,9 @@ export function ProductForm({ product, onChange, isReadonly = false, renderDescr
|
|
|
162
162
|
const lockedForReveal = anyWon;
|
|
163
163
|
const fieldDisabled = isReadonly || lockedForReveal;
|
|
164
164
|
return (_jsxs(_Fragment, { children: [lockedForReveal ? (_jsx(Alert, { variant: "error", title: "Listing locked", children: "At least one prize has been revealed for this draw \u2014 the listing and its fields are now frozen. To rerun a similar draw, clone it into a new prize-draw listing." })) : null, _jsx(Alert, { variant: "warning", title: "Non-refundable", children: "Prize-draw entries are non-refundable once the reveal window opens. Buyers see and must accept this notice before paying." }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "pricePerEntry", label: "Price per entry (\u20B9)", type: "number", value: product.pricePerEntry != null
|
|
165
|
-
? String(
|
|
165
|
+
? String(product.pricePerEntry)
|
|
166
166
|
: "", onChange: (value) => update({
|
|
167
|
-
pricePerEntry: Math.round((parseFloat(value) || 0) * 100),
|
|
167
|
+
pricePerEntry: Math.round((parseFloat(value) || 0) * 100) / 100,
|
|
168
168
|
}), disabled: fieldDisabled, placeholder: "299" }), _jsx(FormField, { name: "prizeMaxEntries", label: "Max entries (pool size)", type: "number", value: String(product.prizeMaxEntries ?? ""), onChange: (value) => update({ prizeMaxEntries: Number(value) || undefined }), disabled: fieldDisabled, placeholder: "100" })] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "prizeRevealWindowStart", label: "Reveal window start", type: "datetime-local", value: (() => {
|
|
169
169
|
const d = resolveDate(product.prizeRevealWindowStart);
|
|
170
170
|
if (!d)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import Link from "next/link";
|
|
5
|
-
import { BaseListingCard, Button, Div, Grid, Row, Span, Stack, Text } from "../../../ui";
|
|
5
|
+
import { BaseListingCard, Button, Div, Grid, PriceDisplay, Row, Span, Stack, Text } from "../../../ui";
|
|
6
6
|
import { MediaImage } from "../../media/MediaImage";
|
|
7
7
|
import { formatCurrency } from "../../../utils/number.formatter";
|
|
8
8
|
import { getDefaultCurrency } from "../../../core/baseline-resolver";
|
|
@@ -90,7 +90,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
|
|
|
90
90
|
})(), (() => {
|
|
91
91
|
const seller = safeDisplayName(product.storeName, "");
|
|
92
92
|
return seller ? (_jsxs(Text, { className: "mt-0.5 text-[11px]", color: "faint", children: ["by ", seller] })) : null;
|
|
93
|
-
})(), product.rating !== undefined && (_jsxs(Row, { className: "mt-1", gap: "xs", children: [_jsx(Span, { className: CLS_STAR, children: "\u2605" }), _jsxs(Span, { className: "text-[11px]", color: "muted", children: [product.rating.toFixed(1), product.reviewCount ? ` (${product.reviewCount})` : ""] })] })), _jsxs(Div, { className: "mt-auto", padding: "t-xs", children: [
|
|
93
|
+
})(), product.rating !== undefined && (_jsxs(Row, { className: "mt-1", gap: "xs", children: [_jsx(Span, { className: CLS_STAR, children: "\u2605" }), _jsxs(Span, { className: "text-[11px]", color: "muted", children: [product.rating.toFixed(1), product.reviewCount ? ` (${product.reviewCount})` : ""] })] })), _jsxs(Div, { className: "mt-auto", padding: "t-xs", children: [_jsx(PriceDisplay, { amount: product.price, originalAmount: product.originalPrice, currency: getDefaultCurrency(), variant: "compact" }), (() => {
|
|
94
94
|
const stock = product.stockCount ?? product.stockQuantity ?? product.availableQuantity;
|
|
95
95
|
if (stock === undefined || !listingPlugin.showsStockQuantity)
|
|
96
96
|
return null;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export interface ProductsIndexListingProps {
|
|
3
3
|
initialData?: any;
|
|
4
|
+
/** Listing types this page's "All" tab spans. Defaults to the consolidated
|
|
5
|
+
* generic set (standard/classified/digital-code/live). Pass a narrower set
|
|
6
|
+
* (e.g. `["art", "stickers"]`) to reuse this component for a different
|
|
7
|
+
* combined browse page. */
|
|
8
|
+
listingTypes?: readonly string[];
|
|
9
|
+
/** Type-filter chip tabs shown above the grid. Defaults to the generic
|
|
10
|
+
* Products tabs; pass a matching set when overriding `listingTypes`. */
|
|
11
|
+
typeTabs?: readonly {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}[];
|
|
15
|
+
searchPlaceholder?: string;
|
|
4
16
|
}
|
|
5
|
-
export declare function ProductsIndexListing({ initialData }: ProductsIndexListingProps): React.JSX.Element;
|
|
17
|
+
export declare function ProductsIndexListing({ initialData, listingTypes, typeTabs, searchPlaceholder, }: ProductsIndexListingProps): React.JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { ShoppingCart, Heart, Columns } from "lucide-react";
|
|
|
5
5
|
import { useRouter } from "next/navigation";
|
|
6
6
|
import { useUrlTable } from "../../../react/hooks/useUrlTable";
|
|
7
7
|
import { useProducts } from "../hooks/useProducts";
|
|
8
|
-
import { BulkActionBar, Div, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Row, Stack, useToast, StickyToolbar } from "../../../ui";
|
|
8
|
+
import { BulkActionBar, Div, FilterChipGroup, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Row, Stack, useToast, StickyToolbar } from "../../../ui";
|
|
9
9
|
import { usePendingTable } from "../../../react/hooks/usePendingTable";
|
|
10
10
|
import { useAuthGate } from "../../../react/hooks/useAuthGate";
|
|
11
11
|
import { ACTION_ID, ACTION_META, COMPARE_MAX_ITEMS } from "../constants/action-defs";
|
|
@@ -23,6 +23,7 @@ import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
|
|
|
23
23
|
import { sortBy } from "../../../constants/sort";
|
|
24
24
|
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
25
25
|
import { useBottomActions } from "../../layout";
|
|
26
|
+
import { GENERIC_PRODUCT_LISTING_TYPES, PRODUCT_TYPE_FILTER_TABS } from "../constants/listing-tabs";
|
|
26
27
|
const __P = {
|
|
27
28
|
p3: "p-[var(--appkit-space-3)]",
|
|
28
29
|
};
|
|
@@ -31,7 +32,7 @@ const __O = {
|
|
|
31
32
|
};
|
|
32
33
|
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
33
34
|
const FILTER_KEYS = [TABLE_KEYS.CATEGORY, TABLE_KEYS.CONDITION, TABLE_KEYS.MIN_PRICE, TABLE_KEYS.MAX_PRICE, TABLE_KEYS.BRAND, TABLE_KEYS.STORE_ID, TABLE_KEYS.FREE_SHIPPING, TABLE_KEYS.TAGS, TABLE_KEYS.FEATURES, TABLE_KEYS.IS_PART_OF_BUNDLE];
|
|
34
|
-
export function ProductsIndexListing({ initialData }) {
|
|
35
|
+
export function ProductsIndexListing({ initialData, listingTypes = GENERIC_PRODUCT_LISTING_TYPES, typeTabs = PRODUCT_TYPE_FILTER_TABS, searchPlaceholder = "Search products...", }) {
|
|
35
36
|
const router = useRouter();
|
|
36
37
|
const table = useUrlTable({ defaults: { pageSize: "24", sort: DEFAULT_SORT } });
|
|
37
38
|
const { showToast } = useToast();
|
|
@@ -41,6 +42,7 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
41
42
|
const [compareIds, setCompareIds] = useState([]);
|
|
42
43
|
const showSold = table.get(TABLE_KEYS.SHOW_SOLD) === "true";
|
|
43
44
|
const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
|
|
45
|
+
const productType = table.get(TABLE_KEYS.LISTING_TYPE) || "All";
|
|
44
46
|
const { pendingTable, filterActiveCount, onFilterApply, onFilterClear, onResetAll, onFilterReset } = usePendingTable(table, FILTER_KEYS);
|
|
45
47
|
const openFilters = useCallback(() => {
|
|
46
48
|
onFilterReset();
|
|
@@ -78,7 +80,7 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
78
80
|
sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
|
|
79
81
|
page: table.getNumber(TABLE_KEYS.PAGE, 1),
|
|
80
82
|
perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
|
|
81
|
-
listingType: "
|
|
83
|
+
listingType: productType === "All" ? listingTypes.join("|") : productType,
|
|
82
84
|
// Hide sold-out items by default. Uses stockQuantity>0 (always-present field)
|
|
83
85
|
// instead of status=="published" because sellers don't actively transition status.
|
|
84
86
|
inStock: showSold ? undefined : true,
|
|
@@ -187,14 +189,14 @@ export function ProductsIndexListing({ initialData }) {
|
|
|
187
189
|
},
|
|
188
190
|
},
|
|
189
191
|
] } } : {});
|
|
190
|
-
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder:
|
|
192
|
+
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: searchPlaceholder, onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PRODUCT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection, toggles: [
|
|
191
193
|
{ label: "Show sold", active: showSold, onChange: (next) => table.set(TABLE_KEYS.SHOW_SOLD, next ? "true" : "") },
|
|
192
194
|
// Inline quick-filter: the highest-frequency drawer-only facet promoted
|
|
193
195
|
// to the sticky toolbar so it doesn't require open-drawer → check → Apply
|
|
194
196
|
// → close for every toggle. The full facet set (category/price/brand/…)
|
|
195
197
|
// remains in <FilterDrawer> below.
|
|
196
198
|
{ label: "Free shipping", active: table.get(TABLE_KEYS.FREE_SHIPPING) === "true", onChange: (next) => table.set(TABLE_KEYS.FREE_SHIPPING, next ? "true" : "") },
|
|
197
|
-
] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
199
|
+
] }), _jsx(Div, { padding: "y-sm", children: _jsx(FilterChipGroup, { label: "Type", tabs: typeTabs, value: productType, onChange: (v) => table.set(TABLE_KEYS.LISTING_TYPE, v === "All" ? "" : v) }) }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
198
200
|
{
|
|
199
201
|
id: ACTION_ID.ADD_TO_CART,
|
|
200
202
|
label: ACTION_META[ACTION_ID.ADD_TO_CART].label,
|
|
@@ -8,6 +8,7 @@ import { ProductsIndexListing } from "./ProductsIndexListing";
|
|
|
8
8
|
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
9
9
|
import { sieveFilter, sieveMultiEq, sieveAnd, SIEVE_OP } from "../../../utils/sieve-builder";
|
|
10
10
|
import { sortBy } from "../../../constants/sort";
|
|
11
|
+
import { GENERIC_PRODUCT_LISTING_TYPES } from "../constants/listing-tabs";
|
|
11
12
|
const DEFAULT_PAGE = 1;
|
|
12
13
|
const DEFAULT_PAGE_SIZE = 24;
|
|
13
14
|
const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
|
|
@@ -16,9 +17,13 @@ function sp(params, key) {
|
|
|
16
17
|
return Array.isArray(v) ? v[0] ?? "" : v ?? "";
|
|
17
18
|
}
|
|
18
19
|
function buildProductFilters(params) {
|
|
20
|
+
const listingTypeParam = sp(params, "listingType");
|
|
21
|
+
const listingType = listingTypeParam && GENERIC_PRODUCT_LISTING_TYPES.includes(listingTypeParam)
|
|
22
|
+
? listingTypeParam
|
|
23
|
+
: GENERIC_PRODUCT_LISTING_TYPES.join("|");
|
|
19
24
|
const parts = [
|
|
20
25
|
sieveFilter(PRODUCT_FIELDS.STATUS, SIEVE_OP.EQ, PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED),
|
|
21
|
-
sieveFilter(PRODUCT_FIELDS.LISTING_TYPE, SIEVE_OP.EQ,
|
|
26
|
+
sieveFilter(PRODUCT_FIELDS.LISTING_TYPE, SIEVE_OP.EQ, listingType),
|
|
22
27
|
];
|
|
23
28
|
const condition = sp(params, "condition");
|
|
24
29
|
if (condition) {
|
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
* Add new tab variants here — never inline the tab list inside the view.
|
|
10
10
|
*/
|
|
11
11
|
import type { ListingType } from "../types";
|
|
12
|
+
/**
|
|
13
|
+
* The consolidated generic `/products` browse tab covers these 4 listing
|
|
14
|
+
* types (auctions/pre-orders/bundles/prize-draws/art+stickers each have
|
|
15
|
+
* their own dedicated public page). Shared between the server-rendered
|
|
16
|
+
* page view and the client listing component so they can't drift apart.
|
|
17
|
+
*/
|
|
18
|
+
export declare const GENERIC_PRODUCT_LISTING_TYPES: readonly ["standard", "classified", "digital-code", "live"];
|
|
12
19
|
export interface ListingTab {
|
|
13
20
|
id: string;
|
|
14
21
|
label: string;
|
|
15
|
-
/** Filter against `products.listingType` when set.
|
|
16
|
-
|
|
22
|
+
/** Filter against `products.listingType` when set. A `|`-joined value
|
|
23
|
+
* (e.g. `"art|stickers"`) is a sievejs OR-group — used by the combined
|
|
24
|
+
* Art & Stickers tab, which spans both listing types on one page. */
|
|
25
|
+
listingType?: ListingType | string;
|
|
17
26
|
/** Set when the tab queries a different collection (e.g. `bundles`). */
|
|
18
27
|
collection?: "bundles";
|
|
19
28
|
/** Set when the tab queries a non-product entity (e.g. `stores`). */
|
|
@@ -54,12 +63,8 @@ export declare const CATEGORY_PAGE_TABS: readonly [{
|
|
|
54
63
|
readonly listingType: "live";
|
|
55
64
|
}, {
|
|
56
65
|
readonly id: "art";
|
|
57
|
-
readonly label: "Art";
|
|
58
|
-
readonly listingType: "art";
|
|
59
|
-
}, {
|
|
60
|
-
readonly id: "stickers";
|
|
61
|
-
readonly label: "Stickers";
|
|
62
|
-
readonly listingType: "stickers";
|
|
66
|
+
readonly label: "Art & Stickers";
|
|
67
|
+
readonly listingType: "art|stickers";
|
|
63
68
|
}, {
|
|
64
69
|
readonly id: "stores";
|
|
65
70
|
readonly label: "Stores";
|
|
@@ -101,12 +106,8 @@ export declare const STORE_PAGE_TABS: readonly [{
|
|
|
101
106
|
readonly listingType: "live";
|
|
102
107
|
}, {
|
|
103
108
|
readonly id: "art";
|
|
104
|
-
readonly label: "Art";
|
|
105
|
-
readonly listingType: "art";
|
|
106
|
-
}, {
|
|
107
|
-
readonly id: "stickers";
|
|
108
|
-
readonly label: "Stickers";
|
|
109
|
-
readonly listingType: "stickers";
|
|
109
|
+
readonly label: "Art & Stickers";
|
|
110
|
+
readonly listingType: "art|stickers";
|
|
110
111
|
}];
|
|
111
112
|
export type StoreTabId = (typeof STORE_PAGE_TABS)[number]["id"];
|
|
112
113
|
/** Tabs shown on the seller-dashboard listings view + admin products list. */
|
|
@@ -187,13 +188,37 @@ export declare const SEARCH_RESULT_TABS: readonly [{
|
|
|
187
188
|
readonly id: "live";
|
|
188
189
|
readonly label: "Live Items";
|
|
189
190
|
readonly listingType: "live";
|
|
191
|
+
}, {
|
|
192
|
+
readonly id: "art";
|
|
193
|
+
readonly label: "Art & Stickers";
|
|
194
|
+
readonly listingType: "art|stickers";
|
|
195
|
+
}];
|
|
196
|
+
export type SearchTabId = (typeof SEARCH_RESULT_TABS)[number]["id"];
|
|
197
|
+
/** In-page type-filter chips on the generic `/products` browse page. */
|
|
198
|
+
export declare const PRODUCT_TYPE_FILTER_TABS: readonly [{
|
|
199
|
+
readonly id: "All";
|
|
200
|
+
readonly label: "All";
|
|
201
|
+
}, {
|
|
202
|
+
readonly id: "standard";
|
|
203
|
+
readonly label: "Standard";
|
|
204
|
+
}, {
|
|
205
|
+
readonly id: "classified";
|
|
206
|
+
readonly label: "Classified";
|
|
207
|
+
}, {
|
|
208
|
+
readonly id: "digital-code";
|
|
209
|
+
readonly label: "Digital Codes";
|
|
210
|
+
}, {
|
|
211
|
+
readonly id: "live";
|
|
212
|
+
readonly label: "Live Items";
|
|
213
|
+
}];
|
|
214
|
+
/** In-page type-filter chips on the combined `/art` (Art & Stickers) page. */
|
|
215
|
+
export declare const ART_STICKERS_TYPE_FILTER_TABS: readonly [{
|
|
216
|
+
readonly id: "All";
|
|
217
|
+
readonly label: "All";
|
|
190
218
|
}, {
|
|
191
219
|
readonly id: "art";
|
|
192
220
|
readonly label: "Art";
|
|
193
|
-
readonly listingType: "art";
|
|
194
221
|
}, {
|
|
195
222
|
readonly id: "stickers";
|
|
196
223
|
readonly label: "Stickers";
|
|
197
|
-
readonly listingType: "stickers";
|
|
198
224
|
}];
|
|
199
|
-
export type SearchTabId = (typeof SEARCH_RESULT_TABS)[number]["id"];
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Add new tab variants here — never inline the tab list inside the view.
|
|
10
10
|
*/
|
|
11
|
+
/**
|
|
12
|
+
* The consolidated generic `/products` browse tab covers these 4 listing
|
|
13
|
+
* types (auctions/pre-orders/bundles/prize-draws/art+stickers each have
|
|
14
|
+
* their own dedicated public page). Shared between the server-rendered
|
|
15
|
+
* page view and the client listing component so they can't drift apart.
|
|
16
|
+
*/
|
|
17
|
+
export const GENERIC_PRODUCT_LISTING_TYPES = ["standard", "classified", "digital-code", "live"];
|
|
11
18
|
/** Tabs shown on `/categories/[slug]` and `/brands/[slug]` detail pages. */
|
|
12
19
|
export const CATEGORY_PAGE_TABS = [
|
|
13
20
|
{ id: "products", label: "Products", listingType: "standard" },
|
|
@@ -18,8 +25,8 @@ export const CATEGORY_PAGE_TABS = [
|
|
|
18
25
|
{ id: "classifieds", label: "Classifieds", listingType: "classified" },
|
|
19
26
|
{ id: "digital-codes", label: "Digital Codes", listingType: "digital-code" },
|
|
20
27
|
{ id: "live", label: "Live Items", listingType: "live" },
|
|
21
|
-
|
|
22
|
-
{ id: "
|
|
28
|
+
// Combined — one public browse page (`/art`) spans both listing types.
|
|
29
|
+
{ id: "art", label: "Art & Stickers", listingType: "art|stickers" },
|
|
23
30
|
{ id: "stores", label: "Stores", entity: "stores" },
|
|
24
31
|
];
|
|
25
32
|
/** Tabs shown on the public `/stores/[slug]` nav bar. */
|
|
@@ -32,8 +39,7 @@ export const STORE_PAGE_TABS = [
|
|
|
32
39
|
{ id: "classifieds", label: "Classifieds", listingType: "classified" },
|
|
33
40
|
{ id: "digital-codes", label: "Digital Codes", listingType: "digital-code" },
|
|
34
41
|
{ id: "live", label: "Live Items", listingType: "live" },
|
|
35
|
-
{ id: "art", label: "Art", listingType: "art" },
|
|
36
|
-
{ id: "stickers", label: "Stickers", listingType: "stickers" },
|
|
42
|
+
{ id: "art", label: "Art & Stickers", listingType: "art|stickers" },
|
|
37
43
|
];
|
|
38
44
|
/** Tabs shown on the seller-dashboard listings view + admin products list. */
|
|
39
45
|
export const SELLER_LISTING_TABS = [
|
|
@@ -59,6 +65,19 @@ export const SEARCH_RESULT_TABS = [
|
|
|
59
65
|
{ id: "classifieds", label: "Classifieds", listingType: "classified" },
|
|
60
66
|
{ id: "digital-codes", label: "Digital Codes", listingType: "digital-code" },
|
|
61
67
|
{ id: "live", label: "Live Items", listingType: "live" },
|
|
62
|
-
{ id: "art", label: "Art", listingType: "art" },
|
|
63
|
-
|
|
68
|
+
{ id: "art", label: "Art & Stickers", listingType: "art|stickers" },
|
|
69
|
+
];
|
|
70
|
+
/** In-page type-filter chips on the generic `/products` browse page. */
|
|
71
|
+
export const PRODUCT_TYPE_FILTER_TABS = [
|
|
72
|
+
{ id: "All", label: "All" },
|
|
73
|
+
{ id: "standard", label: "Standard" },
|
|
74
|
+
{ id: "classified", label: "Classified" },
|
|
75
|
+
{ id: "digital-code", label: "Digital Codes" },
|
|
76
|
+
{ id: "live", label: "Live Items" },
|
|
77
|
+
];
|
|
78
|
+
/** In-page type-filter chips on the combined `/art` (Art & Stickers) page. */
|
|
79
|
+
export const ART_STICKERS_TYPE_FILTER_TABS = [
|
|
80
|
+
{ id: "All", label: "All" },
|
|
81
|
+
{ id: "art", label: "Art" },
|
|
82
|
+
{ id: "stickers", label: "Stickers" },
|
|
64
83
|
];
|
|
@@ -51,8 +51,8 @@ export interface CatalogProductDocument {
|
|
|
51
51
|
identifiers?: CatalogIdentifiers;
|
|
52
52
|
/** Denormalised — count of active offers linking to this catalog row. */
|
|
53
53
|
offerCount: number;
|
|
54
|
-
/** Denormalised — minimum
|
|
55
|
-
|
|
54
|
+
/** Denormalised — minimum price (rupees) across active linked offers. */
|
|
55
|
+
minOfferPrice?: number;
|
|
56
56
|
/** Catalog is searchable / showable on `/catalog/{slug}`. */
|
|
57
57
|
isActive: boolean;
|
|
58
58
|
createdAt: Date;
|
|
@@ -61,10 +61,10 @@ export interface CatalogProductDocument {
|
|
|
61
61
|
promotedBy?: string;
|
|
62
62
|
}
|
|
63
63
|
export declare const CATALOG_COLLECTION: "catalogProducts";
|
|
64
|
-
export declare const CATALOG_PUBLIC_FIELDS: readonly ["id", "slug", "title", "description", "brandSlug", "categorySlug", "card", "gradingService", "images", "identifiers", "offerCount", "
|
|
64
|
+
export declare const CATALOG_PUBLIC_FIELDS: readonly ["id", "slug", "title", "description", "brandSlug", "categorySlug", "card", "gradingService", "images", "identifiers", "offerCount", "minOfferPrice", "isActive", "createdAt", "updatedAt"];
|
|
65
65
|
export declare const CATALOG_UPDATABLE_FIELDS: readonly ["title", "description", "brandSlug", "categorySlug", "card", "gradingService", "images", "identifiers", "isActive"];
|
|
66
|
-
export type CatalogProductCreateInput = Omit<CatalogProductDocument, "id" | "createdAt" | "updatedAt" | "offerCount" | "
|
|
66
|
+
export type CatalogProductCreateInput = Omit<CatalogProductDocument, "id" | "createdAt" | "updatedAt" | "offerCount" | "minOfferPrice"> & {
|
|
67
67
|
offerCount?: number;
|
|
68
|
-
|
|
68
|
+
minOfferPrice?: number;
|
|
69
69
|
};
|
|
70
70
|
export type CatalogProductUpdateInput = Partial<Pick<CatalogProductDocument, (typeof CATALOG_UPDATABLE_FIELDS)[number]>>;
|
|
@@ -95,7 +95,7 @@ export interface ProductLiveItemMeta {
|
|
|
95
95
|
/** Transport details — carrier method, fees, insurance flag. */
|
|
96
96
|
transport: {
|
|
97
97
|
method: "courier" | "in-person" | "specialist";
|
|
98
|
-
|
|
98
|
+
handlingFee?: number;
|
|
99
99
|
insuranceIncluded?: boolean;
|
|
100
100
|
};
|
|
101
101
|
/** Allowed buyer-state ISO 3166-2 codes (e.g. "IN-MH"). */
|
|
@@ -178,7 +178,7 @@ export interface ProductDocument extends BaseDocument {
|
|
|
178
178
|
auctionExtensionMinutes?: number;
|
|
179
179
|
auctionOriginalEndDate?: Date;
|
|
180
180
|
auctionShippingPaidBy?: "seller" | "winner";
|
|
181
|
-
|
|
181
|
+
buyItNowPrice?: number;
|
|
182
182
|
bidsHaveStarted?: boolean;
|
|
183
183
|
grading?: ProductGrading;
|
|
184
184
|
card?: ProductCardMetadata;
|
|
@@ -297,7 +297,7 @@ export interface ProductDocument extends BaseDocument {
|
|
|
297
297
|
*/
|
|
298
298
|
overrides?: Array<{
|
|
299
299
|
providerId: string;
|
|
300
|
-
|
|
300
|
+
fee?: number;
|
|
301
301
|
etaDaysMin?: number;
|
|
302
302
|
etaDaysMax?: number;
|
|
303
303
|
}>;
|
|
@@ -344,8 +344,8 @@ export declare const ProductStatusValues: {
|
|
|
344
344
|
export declare const PRODUCT_COLLECTION: "products";
|
|
345
345
|
export declare const PRODUCT_INDEXED_FIELDS: readonly ["storeId", "status", "category", "featured", "listingType", "isPromoted", "isOnSale", "isSold", "searchTokens", "createdAt", "barcodeId"];
|
|
346
346
|
export declare const DEFAULT_PRODUCT_DATA: Partial<ProductDocument>;
|
|
347
|
-
export declare const PRODUCT_PUBLIC_FIELDS: readonly ["id", "title", "description", "category", "subcategory", "brand", "price", "currency", "stockQuantity", "availableQuantity", "images", "status", "storeName", "featured", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "listingType", "auctionEndDate", "startingBid", "currentBid", "bidCount", "reservePrice", "buyNowPrice", "minBidIncrement", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "
|
|
348
|
-
export declare const PRODUCT_UPDATABLE_FIELDS: readonly ["title", "description", "category", "subcategory", "brand", "price", "stockQuantity", "images", "status", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "pickupAddressId", "condition", "insurance", "shippingPaidBy", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "reservePrice", "buyNowPrice", "minBidIncrement", "
|
|
347
|
+
export declare const PRODUCT_PUBLIC_FIELDS: readonly ["id", "title", "description", "category", "subcategory", "brand", "price", "currency", "stockQuantity", "availableQuantity", "images", "status", "storeName", "featured", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "listingType", "auctionEndDate", "startingBid", "currentBid", "bidCount", "reservePrice", "buyNowPrice", "minBidIncrement", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "buyItNowPrice", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderCurrentCount", "preOrderProductionStatus", "preOrderCancellable", "condition", "insurance", "insuranceCost", "shippingPaidBy", "isPromoted", "isOnSale", "isSold", "slug", "seoTitle", "seoDescription", "seoKeywords", "viewCount", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "createdAt"];
|
|
348
|
+
export declare const PRODUCT_UPDATABLE_FIELDS: readonly ["title", "description", "category", "subcategory", "brand", "price", "stockQuantity", "images", "status", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "pickupAddressId", "condition", "insurance", "shippingPaidBy", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "reservePrice", "buyNowPrice", "minBidIncrement", "buyItNowPrice", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "listingType", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderProductionStatus", "preOrderCancellable", "isOnSale", "isSold", "allowShipBeforeEmiComplete", "printMeta", "seoTitle", "seoDescription", "seoKeywords", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "barcodeId"];
|
|
349
349
|
export type ProductCreateInput = Omit<ProductDocument, "id" | "createdAt" | "updatedAt" | "availableQuantity" | "bidCount" | "currentBid" | "auctionOriginalEndDate">;
|
|
350
350
|
export type ProductUpdateInput = Partial<Pick<ProductDocument, (typeof PRODUCT_UPDATABLE_FIELDS)[number]>>;
|
|
351
351
|
export type ProductAdminUpdateInput = Partial<Omit<ProductDocument, "id" | "createdAt">>;
|
|
@@ -77,7 +77,7 @@ export const PRODUCT_PUBLIC_FIELDS = [
|
|
|
77
77
|
"auctionExtensionMinutes",
|
|
78
78
|
"auctionShippingPaidBy",
|
|
79
79
|
// SB-UNI-H 2026-05-13 — eBay hybrid BIN.
|
|
80
|
-
"
|
|
80
|
+
"buyItNowPrice",
|
|
81
81
|
"bidsHaveStarted",
|
|
82
82
|
// SB-UNI-G 2026-05-13 — TCGPlayer grading + card metadata.
|
|
83
83
|
"grading",
|
|
@@ -143,7 +143,7 @@ export const PRODUCT_UPDATABLE_FIELDS = [
|
|
|
143
143
|
"buyNowPrice",
|
|
144
144
|
"minBidIncrement",
|
|
145
145
|
// SB-UNI-H 2026-05-13 — eBay hybrid BIN updatable.
|
|
146
|
-
"
|
|
146
|
+
"buyItNowPrice",
|
|
147
147
|
"bidsHaveStarted",
|
|
148
148
|
// SB-UNI-G 2026-05-13 — TCGPlayer grading + card metadata updatable.
|
|
149
149
|
"grading",
|
|
@@ -173,8 +173,11 @@ export interface ProductListParams {
|
|
|
173
173
|
minPrice?: number;
|
|
174
174
|
maxPrice?: number;
|
|
175
175
|
inStock?: boolean;
|
|
176
|
-
/** Canonical listing-kind discriminator (SB1-G Phase 4).
|
|
177
|
-
|
|
176
|
+
/** Canonical listing-kind discriminator (SB1-G Phase 4). Accepts a single
|
|
177
|
+
* `ListingType`, or a `|`-joined multi-value string (sievejs OR-group,
|
|
178
|
+
* e.g. `"standard|classified|digital-code|live"`) for the consolidated
|
|
179
|
+
* generic Products browse page. */
|
|
180
|
+
listingType?: ListingType | string;
|
|
178
181
|
storeId?: string;
|
|
179
182
|
sort?: string;
|
|
180
183
|
page?: number;
|
|
@@ -63,7 +63,7 @@ function formatDiscount(n, labels) {
|
|
|
63
63
|
if (n.type === "percentage")
|
|
64
64
|
return `${n.discountValue}% ${labels.off}`;
|
|
65
65
|
if (n.type === "fixed")
|
|
66
|
-
return `₹${
|
|
66
|
+
return `₹${n.discountValue.toFixed(0)} ${labels.off}`;
|
|
67
67
|
if (n.type === "free_shipping")
|
|
68
68
|
return labels.freeShipping;
|
|
69
69
|
if (n.type === "buy_x_get_y")
|
|
@@ -167,7 +167,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
|
|
|
167
167
|
setBusy(null);
|
|
168
168
|
}
|
|
169
169
|
};
|
|
170
|
-
return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, onTouchCancel: onSelect && !isSelected ? longPress.onTouchCancel : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-neutral-200/70 text-[10px] tracking-wide bg-[var(--appkit-color-border)]/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx(Button, { variant: "outline", type: "button", onClick: handleCopy, rounded: "md", paddingX: "sm", paddingY: "none", textSize: "xs", weight: "semibold", className: "shrink-0 hover:opacity-80 active:scale-95 border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx(Button, { variant: "primary", type: "button", onClick: handleClaim, disabled: claiming, rounded: "md", paddingX: "md", paddingY: "xs", textSize: "xs", weight: "semibold", className: "w-full active:scale-95 bg-[var(--appkit-color-primary-700)] hover:bg-[var(--appkit-color-primary-800)]", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9",
|
|
170
|
+
return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, onTouchCancel: onSelect && !isSelected ? longPress.onTouchCancel : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-neutral-200/70 text-[10px] tracking-wide bg-[var(--appkit-color-border)]/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx(Button, { variant: "outline", type: "button", onClick: handleCopy, rounded: "md", paddingX: "sm", paddingY: "none", textSize: "xs", weight: "semibold", className: "shrink-0 hover:opacity-80 active:scale-95 border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx(Button, { variant: "primary", type: "button", onClick: handleClaim, disabled: claiming, rounded: "md", paddingX: "md", paddingY: "xs", textSize: "xs", weight: "semibold", className: "w-full active:scale-95 bg-[var(--appkit-color-primary-700)] hover:bg-[var(--appkit-color-primary-800)]", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", n.minOrderAmount.toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", justify: "end", className: "mt-auto", padding: "t-sm", children: [onEdit && (_jsx(IconButton, { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, variant: "ghost", rounded: "lg", className: "text-[var(--appkit-color-text-muted)]", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx(IconButton, { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, variant: "ghost", rounded: "lg", className: "text-[var(--appkit-color-text-muted)]", children: n.isActive
|
|
171
171
|
? _jsx(ToggleRight, { className: CLS_TOGGLE_ON })
|
|
172
172
|
: _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx(IconButton, { type: "button", onClick: () => setDeleteConfirmOpen(true), disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, variant: "ghost", rounded: "lg", className: CLS_DELETE_BTN, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] })), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Coupon", message: labels.deleteConfirm, onConfirm: handleDeleteConfirmed, onClose: () => setDeleteConfirmOpen(false), isDeleting: busy === "delete" }))] }));
|
|
173
173
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { CouponType } from "../types";
|
|
5
5
|
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
6
6
|
export interface DiscountConfig {
|
|
7
|
+
/** Percentage (0-100) when type === "percentage"; decimal rupees when type === "fixed". */
|
|
7
8
|
value: number;
|
|
8
9
|
maxDiscount?: number;
|
|
9
10
|
minPurchase?: number;
|
|
@@ -16,6 +17,7 @@ export interface BXGYConfig {
|
|
|
16
17
|
}
|
|
17
18
|
export interface TieredDiscount {
|
|
18
19
|
minAmount: number;
|
|
20
|
+
/** Percentage (0-100) when the coupon type === "percentage"; decimal rupees when type === "fixed". */
|
|
19
21
|
discountValue: number;
|
|
20
22
|
}
|
|
21
23
|
export interface UsageConfig {
|
|
@@ -138,6 +138,7 @@ export function calculateDiscount(coupon, orderTotal) {
|
|
|
138
138
|
let discountAmount = 0;
|
|
139
139
|
switch (coupon.type) {
|
|
140
140
|
case "percentage":
|
|
141
|
+
// audit-money-units-ok: percentage divisor (coupon.discount.value is 0-100), not paise
|
|
141
142
|
discountAmount = (orderTotal * coupon.discount.value) / 100;
|
|
142
143
|
if (coupon.discount.maxDiscount &&
|
|
143
144
|
discountAmount > coupon.discount.maxDiscount) {
|