@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
|
@@ -9,28 +9,28 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
*/
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
import { Button, Div, Row, Stack, Text } from "../../../ui";
|
|
12
|
-
import { formatCurrency } from "../../../utils/number.formatter";
|
|
12
|
+
import { formatCurrency, roundRupees } from "../../../utils/number.formatter";
|
|
13
13
|
import { REFUND_COPY } from "../../../_internal/shared/features/orders/refund-copy";
|
|
14
14
|
/** Resolve the effective flat fee for a provider given the current subtotal. */
|
|
15
|
-
function resolveProviderFee(p,
|
|
15
|
+
function resolveProviderFee(p, subtotal) {
|
|
16
16
|
const { fee } = p;
|
|
17
|
-
if (fee.
|
|
17
|
+
if (fee.freeAbove !== undefined && subtotal >= fee.freeAbove)
|
|
18
18
|
return 0;
|
|
19
|
-
let total = fee.
|
|
19
|
+
let total = fee.flat ?? 0;
|
|
20
20
|
if (fee.percentOfOrder !== undefined) {
|
|
21
|
-
total +=
|
|
21
|
+
total += roundRupees((fee.percentOfOrder / 100) * subtotal);
|
|
22
22
|
}
|
|
23
|
-
if (fee.
|
|
24
|
-
total = Math.max(total, fee.
|
|
23
|
+
if (fee.min !== undefined)
|
|
24
|
+
total = Math.max(total, fee.min);
|
|
25
25
|
return total;
|
|
26
26
|
}
|
|
27
|
-
export function ShippingPicker({ providers, selectedProviderId,
|
|
27
|
+
export function ShippingPicker({ providers, selectedProviderId, subtotal = 0, onPickProvider, isLoading = false, className = "", }) {
|
|
28
28
|
const [pending, setPending] = useState(false);
|
|
29
29
|
if (providers.length === 0) {
|
|
30
30
|
return (_jsx(Text, { size: "sm", color: "muted", className: className, children: REFUND_COPY.shipping.noOptions }));
|
|
31
31
|
}
|
|
32
32
|
const handleSelect = async (p) => {
|
|
33
|
-
const fee = resolveProviderFee(p,
|
|
33
|
+
const fee = resolveProviderFee(p, subtotal);
|
|
34
34
|
setPending(true);
|
|
35
35
|
try {
|
|
36
36
|
await onPickProvider(p.providerId, fee);
|
|
@@ -40,9 +40,9 @@ export function ShippingPicker({ providers, selectedProviderId, subtotalInPaise
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
return (_jsx(Stack, { gap: "xs", className: className, role: "radiogroup", "aria-label": "Shipping options", children: providers.map((p) => {
|
|
43
|
-
const fee = resolveProviderFee(p,
|
|
43
|
+
const fee = resolveProviderFee(p, subtotal);
|
|
44
44
|
const selected = p.providerId === selectedProviderId;
|
|
45
45
|
const disabled = isLoading || pending;
|
|
46
|
-
return (_jsx(Button, { type: "button", variant: selected ? "primary" : "outline", size: "sm", disabled: disabled, onClick: () => handleSelect(p), "aria-checked": selected, role: "radio", className: "w-full justify-start text-left", children: _jsxs(Row, { gap: "sm", className: "w-full", wrap: true, align: "center", children: [_jsxs(Div, { className: "flex-1", children: [_jsx(Text, { size: "sm", weight: selected ? "semibold" : "normal", children: p.label }), _jsx(Text, { size: "xs", color: "muted", children: REFUND_COPY.shipping.etaFormat(p.etaDaysMin, p.etaDaysMax) })] }), _jsx(Text, { size: "sm", weight: "semibold", children: fee === 0 ? REFUND_COPY.shipping.freeLabel : formatCurrency(fee
|
|
46
|
+
return (_jsx(Button, { type: "button", variant: selected ? "primary" : "outline", size: "sm", disabled: disabled, onClick: () => handleSelect(p), "aria-checked": selected, role: "radio", className: "w-full justify-start text-left", children: _jsxs(Row, { gap: "sm", className: "w-full", wrap: true, align: "center", children: [_jsxs(Div, { className: "flex-1", children: [_jsx(Text, { size: "sm", weight: selected ? "semibold" : "normal", children: p.label }), _jsx(Text, { size: "xs", color: "muted", children: REFUND_COPY.shipping.etaFormat(p.etaDaysMin, p.etaDaysMax) })] }), _jsx(Text, { size: "sm", weight: "semibold", children: fee === 0 ? REFUND_COPY.shipping.freeLabel : formatCurrency(fee, "INR") })] }) }, p.providerId));
|
|
47
47
|
}) }));
|
|
48
48
|
}
|
|
@@ -19,7 +19,7 @@ export declare class CartRepository extends BaseRepository<CartDocument> {
|
|
|
19
19
|
getSubtotal(cart: CartDocument): number;
|
|
20
20
|
addCoupon(userId: string, coupon: CartAppliedCoupon): Promise<void>;
|
|
21
21
|
removeCoupon(userId: string, code: string): Promise<void>;
|
|
22
|
-
updateItemShipping(userId: string, itemId: string, providerId: string,
|
|
22
|
+
updateItemShipping(userId: string, itemId: string, providerId: string, fee: number): Promise<CartDocument>;
|
|
23
23
|
clearAllCoupons(userId: string): Promise<void>;
|
|
24
24
|
setSelectedItems(userId: string, itemIds: string[] | null): Promise<void>;
|
|
25
25
|
/**
|
|
@@ -231,7 +231,7 @@ export class CartRepository extends BaseRepository {
|
|
|
231
231
|
.doc(userId)
|
|
232
232
|
.set({ appliedCoupons: updated, updatedAt: new Date() }, { merge: true });
|
|
233
233
|
}
|
|
234
|
-
async updateItemShipping(userId, itemId, providerId,
|
|
234
|
+
async updateItemShipping(userId, itemId, providerId, fee) {
|
|
235
235
|
try {
|
|
236
236
|
const cart = await this.findByUserId(userId);
|
|
237
237
|
if (!cart)
|
|
@@ -243,7 +243,7 @@ export class CartRepository extends BaseRepository {
|
|
|
243
243
|
items[itemIndex] = {
|
|
244
244
|
...items[itemIndex],
|
|
245
245
|
chosenShippingProviderId: providerId,
|
|
246
|
-
|
|
246
|
+
chosenShippingFee: fee,
|
|
247
247
|
updatedAt: new Date(),
|
|
248
248
|
};
|
|
249
249
|
const updatedCart = { ...cart, items, updatedAt: new Date() };
|
|
@@ -35,7 +35,7 @@ export interface CartItemDocument {
|
|
|
35
35
|
* SB-UNI-4 2026-05-13 — bundle identifier when this cart line represents a
|
|
36
36
|
* bundle (categoryType:"bundle" row on the categories collection). When set,
|
|
37
37
|
* `productId` points at the bundle category's id, `price` is the locked
|
|
38
|
-
*
|
|
38
|
+
* bundlePrice, and `bundleProductIds` snapshots the member product
|
|
39
39
|
* ids at add-to-cart time. Order-side fan-out into per-product OrderItem
|
|
40
40
|
* entries lands in S-SBUNI-5 (checkout-side stock decrement + per-store
|
|
41
41
|
* grouping); until then the foundation is here but BundleDetailView keeps
|
|
@@ -51,7 +51,7 @@ export interface CartItemDocument {
|
|
|
51
51
|
*/
|
|
52
52
|
chosenShippingProviderId?: string;
|
|
53
53
|
/** Fee in paise for the chosen provider, snapshotted at cart time. */
|
|
54
|
-
|
|
54
|
+
chosenShippingFee?: number;
|
|
55
55
|
addedAt: Date;
|
|
56
56
|
updatedAt: Date;
|
|
57
57
|
}
|
|
@@ -26,7 +26,7 @@ export function CatalogueItemEditorView({ item, onSaved }) {
|
|
|
26
26
|
const [title, setTitle] = React.useState(item?.title ?? "");
|
|
27
27
|
const [description, setDescription] = React.useState(item?.description ?? "");
|
|
28
28
|
const [condition, setCondition] = React.useState(item?.condition ?? "");
|
|
29
|
-
const [price, setPrice] = React.useState(item?.price ? String(item.price
|
|
29
|
+
const [price, setPrice] = React.useState(item?.price ? String(item.price) : "0");
|
|
30
30
|
const [quantity, setQuantity] = React.useState(String(item?.quantity ?? 1));
|
|
31
31
|
const [visibility, setVisibility] = React.useState(item?.visibility ?? "public");
|
|
32
32
|
const [images, setImages] = React.useState(item?.images ?? []);
|
|
@@ -46,7 +46,7 @@ export function CatalogueItemEditorView({ item, onSaved }) {
|
|
|
46
46
|
title,
|
|
47
47
|
description: description || undefined,
|
|
48
48
|
condition: condition || undefined,
|
|
49
|
-
price: Math.round(Number(price) * 100),
|
|
49
|
+
price: Math.round(Number(price) * 100) / 100,
|
|
50
50
|
quantity: Number(quantity),
|
|
51
51
|
visibility,
|
|
52
52
|
images,
|
|
@@ -65,7 +65,7 @@ export function CatalogueItemEditorView({ item, onSaved }) {
|
|
|
65
65
|
const parsed = createCatalogueItemSchema.safeParse({
|
|
66
66
|
title,
|
|
67
67
|
images,
|
|
68
|
-
price: Math.round(Number(price) * 100),
|
|
68
|
+
price: Math.round(Number(price) * 100) / 100,
|
|
69
69
|
quantity: Number(quantity),
|
|
70
70
|
visibility,
|
|
71
71
|
});
|
|
@@ -5,7 +5,7 @@ import { Div, Grid, Heading, Skeleton, Text } from "../../../ui";
|
|
|
5
5
|
import { MediaImage } from "../../media/MediaImage";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
7
|
import { ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
8
|
-
import {
|
|
8
|
+
import { formatCurrency } from "../../../utils/number.formatter";
|
|
9
9
|
export function PublicCatalogueView({ ownerSlug }) {
|
|
10
10
|
const { data, isLoading } = useQuery({
|
|
11
11
|
queryKey: ["catalogue", "public", ownerSlug],
|
|
@@ -18,5 +18,5 @@ export function PublicCatalogueView({ ownerSlug }) {
|
|
|
18
18
|
if (items.length === 0) {
|
|
19
19
|
return _jsx(Text, { variant: "secondary", children: "Nothing public here yet." });
|
|
20
20
|
}
|
|
21
|
-
return (_jsx(Grid, { cols: 4, gap: "md", children: items.map((item) => (_jsxs(Div, { rounded: "xl", border: "default", padding: "md", surface: "card", children: [_jsx(MediaImage, { src: item.mainImage || item.images[0] || "", alt: item.title, size: "card" }), _jsx(Div, { padding: "t-sm", children: _jsx(Heading, { level: 4, size: "sm", children: item.title }) }), typeof item.price === "number" && item.price > 0 && (_jsx(Text, { size: "sm", color: "muted", children:
|
|
21
|
+
return (_jsx(Grid, { cols: 4, gap: "md", children: items.map((item) => (_jsxs(Div, { rounded: "xl", border: "default", padding: "md", surface: "card", children: [_jsx(MediaImage, { src: item.mainImage || item.images[0] || "", alt: item.title, size: "card" }), _jsx(Div, { padding: "t-sm", children: _jsx(Heading, { level: 4, size: "sm", children: item.title }) }), typeof item.price === "number" && item.price > 0 && (_jsx(Text, { size: "sm", color: "muted", children: formatCurrency(item.price) }))] }, item.id))) }));
|
|
22
22
|
}
|
|
@@ -18,7 +18,7 @@ export const createCatalogueItemSchema = z.object({
|
|
|
18
18
|
condition: productConditionSchema.optional(),
|
|
19
19
|
categorySlugs: z.array(z.string()).optional(),
|
|
20
20
|
brandSlug: z.string().optional(),
|
|
21
|
-
price: z.number().
|
|
21
|
+
price: z.number().min(0).optional(),
|
|
22
22
|
quantity: z.number().int().min(1).default(1),
|
|
23
23
|
visibility: z.enum(["public", "private"]).default("public"),
|
|
24
24
|
});
|
|
@@ -22,7 +22,7 @@ function toGalleryImages(members) {
|
|
|
22
22
|
alt: p.title,
|
|
23
23
|
badge: `#${i + 1}`,
|
|
24
24
|
caption: p.title,
|
|
25
|
-
sub: formatCurrency(
|
|
25
|
+
sub: formatCurrency(p.price ?? 0, p.currency ?? "INR"),
|
|
26
26
|
}));
|
|
27
27
|
}
|
|
28
28
|
function makeBundleItemClickHandler(p, idx, onItemClick, setLightboxIndex) {
|
|
@@ -43,7 +43,7 @@ export function BundleCollage({ members, onItemClick }) {
|
|
|
43
43
|
return (_jsxs(_Fragment, { children: [_jsx(Div, { layout: "grid", gap: "3", className: "grid-cols-2 sm:grid-cols-3 md:grid-cols-4", children: members.map((p, idx) => {
|
|
44
44
|
const cover = p.mainImage ?? p.images?.[0];
|
|
45
45
|
const href = String(ROUTES.PUBLIC.PRODUCT_DETAIL?.(p.slug ?? p.id) ?? "#");
|
|
46
|
-
return (_jsxs(Div, { className: "group relative overflow-hidden border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] transition-transform hover:scale-[1.01]", rounded: "lg", children: [_jsxs(Button, { variant: "ghost", type: "button", onClick: makeBundleItemClickHandler(p, idx, onItemClick, setLightboxIndex), paddingX: "none", paddingY: "none", rounded: "none", className: "relative block aspect-square w-full overflow-hidden focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-primary)]", "aria-label": `View ${p.title} in lightbox`, children: [cover ? (_jsx(MediaImage, { src: cover, alt: p.title, size: "card", className: "transition-transform group-hover:scale-105" })) : (_jsx(Row, { textSize: "3xl", surface: "muted", className: "absolute inset-0", align: "center", justify: "center", children: PLACEHOLDER_EMOJI })), _jsxs(Div, { textWeight: "semibold", textSize: "xs", surface: "overlay-xl", padding: "chip-2xs", className: "absolute left-2 top-2 text-white", rounded: "default", children: ["#", idx + 1] })] }), _jsxs(Div, { padding: "xs", children: [_jsx(Link, { href: href, className: "line-clamp-2 text-[length:var(--appkit-text-sm)] font-medium hover:underline", children: p.title }), _jsx(Text, { className: "mt-0.5 text-[var(--appkit-color-text-muted)]", size: "xs", children: formatCurrency(
|
|
46
|
+
return (_jsxs(Div, { className: "group relative overflow-hidden border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] transition-transform hover:scale-[1.01]", rounded: "lg", children: [_jsxs(Button, { variant: "ghost", type: "button", onClick: makeBundleItemClickHandler(p, idx, onItemClick, setLightboxIndex), paddingX: "none", paddingY: "none", rounded: "none", className: "relative block aspect-square w-full overflow-hidden focus-visible:ring-2 focus-visible:ring-[var(--appkit-color-primary)]", "aria-label": `View ${p.title} in lightbox`, children: [cover ? (_jsx(MediaImage, { src: cover, alt: p.title, size: "card", className: "transition-transform group-hover:scale-105" })) : (_jsx(Row, { textSize: "3xl", surface: "muted", className: "absolute inset-0", align: "center", justify: "center", children: PLACEHOLDER_EMOJI })), _jsxs(Div, { textWeight: "semibold", textSize: "xs", surface: "overlay-xl", padding: "chip-2xs", className: "absolute left-2 top-2 text-white", rounded: "default", children: ["#", idx + 1] })] }), _jsxs(Div, { padding: "xs", children: [_jsx(Link, { href: href, className: "line-clamp-2 text-[length:var(--appkit-text-sm)] font-medium hover:underline", children: p.title }), _jsx(Text, { className: "mt-0.5 text-[var(--appkit-color-text-muted)]", size: "xs", children: formatCurrency(p.price ?? 0, p.currency ?? "INR") })] })] }, p.id));
|
|
47
47
|
}) }), _jsx(ImageLightbox, { images: galleryImages, activeIndex: lightboxIndex, onClose: () => setLightboxIndex(null), onNavigate: (i) => setLightboxIndex(i), showThumbnails: true })] }));
|
|
48
48
|
}
|
|
49
49
|
export default BundleCollage;
|
|
@@ -19,8 +19,8 @@ export function BundleDetailView({ bundle, members = [], onBuyNow, }) {
|
|
|
19
19
|
const memberCount = members.length || bundle.bundleProductIds?.length || 0;
|
|
20
20
|
const stock = bundle.bundleStockStatus ?? "in_stock";
|
|
21
21
|
const cover = bundle.display?.coverImage;
|
|
22
|
-
const priceLabel = bundle.
|
|
23
|
-
? formatCurrency(bundle.
|
|
22
|
+
const priceLabel = bundle.bundlePrice
|
|
23
|
+
? formatCurrency(bundle.bundlePrice, "INR")
|
|
24
24
|
: BUNDLE_COPY.detail.priceFallback;
|
|
25
25
|
return (_jsx(Main, { children: _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "lg", children: [_jsxs(Stack, { gap: "lg", direction: "md-row", align: "start", children: [_jsx(Div, { className: "w-full md:w-2/5", children: members.length > 0 ? (_jsx(BundleCollage, { members: members })) : (_jsx(Div, { className: `aspect-video w-full ${__O.hidden}`, rounded: "2xl", surface: "subtle", children: _jsx(Div, { className: "h-full w-full", children: _jsx(MediaImage, { src: cover, alt: bundle.name, size: "hero", fallback: PLACEHOLDER_EMOJI }) }) })) }), _jsxs(Stack, { gap: "md", className: "flex-1", children: [_jsx(Heading, { level: 1, size: "3xl", weight: "semibold", color: "primary", children: bundle.name }), _jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Text, { size: "lg", weight: "bold", children: priceLabel }), _jsxs(Text, { size: "sm", color: "muted", children: ["\u00B7 ", BUNDLE_COPY.detail.itemCount(memberCount)] }), _jsx(Badge, { variant: BUNDLE_STOCK_VARIANT[stock], children: STOCK_BADGE_TEXT[stock] })] }), bundle.description && (_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-[var(--appkit-color-text-muted)]", size: "sm", weight: "semibold", children: BUNDLE_COPY.detailDescriptionHeading }), _jsx(Text, { className: "whitespace-pre-line", children: bundle.description })] })), onBuyNow ? (_jsx(BundleBuyNowCta, { bundleSlug: bundle.slug, outOfStock: stock === "out_of_stock", onBuyNow: onBuyNow })) : (_jsxs(Div, { textSize: "sm", className: "border-dashed", border: "strong", surface: "muted", rounded: "xl", padding: "md", "aria-live": "polite", children: [_jsx(Text, { weight: "semibold", className: "mb-1 block", children: BUNDLE_COPY.detail.ctaDisabled }), _jsx(Text, { size: "sm", color: "muted", children: BUNDLE_COPY.detail.ctaHint })] }))] })] }), _jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 2, size: "xl", weight: "semibold", color: "primary", children: BUNDLE_COPY.detailItemsHeading }), members.length === 0 ? (_jsx(Text, { color: "muted", children: BUNDLE_COPY.detail.emptyMembers })) : (_jsx(Ul, { gap: "2", className: "grid grid-cols-1 sm:grid-cols-2", children: members.map((p, i) => (_jsxs(Li, { layout: "flex-center", gap: "2", rounded: "lg", border: "subtle", padding: "inlineSm", textSize: "sm", children: [_jsxs(Span, { size: "xs", weight: "semibold", className: "w-5", color: "faint", children: ["#", i + 1] }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCT_DETAIL?.(p.slug ?? p.id) ?? "#"), className: "flex-1 truncate font-medium hover:underline hover:text-primary", children: p.title })] }, p.id))) }))] })] }) }) }) }));
|
|
26
26
|
}
|
|
@@ -41,7 +41,7 @@ function renderBundleSearchResults(props) {
|
|
|
41
41
|
return (_jsxs(_Fragment, { children: [searchError && _jsx(Text, { size: "sm", color: "danger", children: searchError }), isSearching && _jsx(Text, { size: "sm", color: "muted", children: BUNDLE_COPY.picker.searchingHint }), !isSearching && debouncedQuery.length >= 2 && results.length === 0 && !searchError && (_jsx(Text, { size: "sm", color: "muted", children: BUNDLE_COPY.picker.noMatches(debouncedQuery) })), results.length > 0 && (_jsx(Div, { className: `max-h-72 ${__O.yAuto}`, rounded: "lg", border: "default", children: results.map((r) => {
|
|
42
42
|
const isSelected = selectedSet.has(r.id);
|
|
43
43
|
const atCap = !isSelected && value.length >= maxItems;
|
|
44
|
-
return (_jsxs(Row, { border: "subtle", gap: "sm", align: "center", className: `border-b last:border-b-0 ${isSelected ? CLS_ROW_SELECTED : ""} ${atCap ? "opacity-50" : ""}`, padding: "inlineSm", children: [_jsx(Checkbox, { checked: isSelected, disabled: atCap, onChange: () => toggle(r.id), "aria-label": BUNDLE_COPY.picker.toggleAria(r.title) }), _jsxs(Stack, { gap: "xs", className: "flex-1", children: [_jsx(Text, { size: "sm", weight: "medium", children: r.title }), _jsxs(Row, { gap: "sm", children: [_jsx(Text, { size: "xs", color: "muted", children: r.id }), typeof r.
|
|
44
|
+
return (_jsxs(Row, { border: "subtle", gap: "sm", align: "center", className: `border-b last:border-b-0 ${isSelected ? CLS_ROW_SELECTED : ""} ${atCap ? "opacity-50" : ""}`, padding: "inlineSm", children: [_jsx(Checkbox, { checked: isSelected, disabled: atCap, onChange: () => toggle(r.id), "aria-label": BUNDLE_COPY.picker.toggleAria(r.title) }), _jsxs(Stack, { gap: "xs", className: "flex-1", children: [_jsx(Text, { size: "sm", weight: "medium", children: r.title }), _jsxs(Row, { gap: "sm", children: [_jsx(Text, { size: "xs", color: "muted", children: r.id }), typeof r.price === "number" && _jsxs(Text, { size: "xs", color: "muted", children: ["\u00B7 \u20B9", r.price.toLocaleString("en-IN")] })] })] })] }, r.id));
|
|
45
45
|
}) }))] }));
|
|
46
46
|
}
|
|
47
47
|
export function BundleItemsPicker({ value, onChange, fetchProducts, minItems = BUNDLE_MIN_ITEMS, maxItems = BUNDLE_MAX_ITEMS, initialMetadata = {}, }) {
|
|
@@ -142,7 +142,7 @@ export async function defaultBundleItemsFetch(query) {
|
|
|
142
142
|
: Array.isArray(rec.images) && typeof rec.images[0] === "string"
|
|
143
143
|
? rec.images[0]
|
|
144
144
|
: undefined,
|
|
145
|
-
|
|
145
|
+
price: typeof rec.price === "number" ? rec.price : undefined,
|
|
146
146
|
storeId: typeof rec.storeId === "string" ? rec.storeId : undefined,
|
|
147
147
|
};
|
|
148
148
|
})
|
|
@@ -65,9 +65,9 @@ export function CategoryBundlesListing({ initialBundles, brandName, onBuyNow, })
|
|
|
65
65
|
}
|
|
66
66
|
list = [...list].sort((a, b) => {
|
|
67
67
|
if (sort === "price")
|
|
68
|
-
return (a.
|
|
68
|
+
return (a.bundlePrice ?? 0) - (b.bundlePrice ?? 0);
|
|
69
69
|
if (sort === "-price")
|
|
70
|
-
return (b.
|
|
70
|
+
return (b.bundlePrice ?? 0) - (a.bundlePrice ?? 0);
|
|
71
71
|
if (sort === "createdAt") {
|
|
72
72
|
const aT = a.createdAt instanceof Date ? a.createdAt.getTime() : 0;
|
|
73
73
|
const bT = b.createdAt instanceof Date ? b.createdAt.getTime() : 0;
|
|
@@ -136,7 +136,7 @@ export interface CategoryDocument extends BaseDocument {
|
|
|
136
136
|
*/
|
|
137
137
|
bundleKind?: "special" | "brand";
|
|
138
138
|
/** Discounted bundle price in paise. */
|
|
139
|
-
|
|
139
|
+
bundlePrice?: number;
|
|
140
140
|
/** Rule resolving the bundle's member products — static list or live query. */
|
|
141
141
|
bundleQueryRule?: BundleQueryRule;
|
|
142
142
|
/** Snapshot stock state — recomputed by onProductStockChange. */
|
|
@@ -231,7 +231,7 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
|
|
|
231
231
|
brandFounded: z.ZodOptional<z.ZodNumber>;
|
|
232
232
|
brandBannerImage: z.ZodOptional<z.ZodString>;
|
|
233
233
|
bundleKind: z.ZodOptional<z.ZodEnum<["special", "brand"]>>;
|
|
234
|
-
|
|
234
|
+
bundlePrice: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
|
235
235
|
bundleQueryRule: z.ZodOptional<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
|
|
236
236
|
type: z.ZodLiteral<"static">;
|
|
237
237
|
productIds: z.ZodArray<z.ZodString, "many">;
|
|
@@ -443,7 +443,7 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
|
|
|
443
443
|
brandCountry?: string | undefined;
|
|
444
444
|
brandFounded?: number | undefined;
|
|
445
445
|
brandBannerImage?: string | undefined;
|
|
446
|
-
|
|
446
|
+
bundlePrice?: number | undefined;
|
|
447
447
|
bundleQueryRule?: {
|
|
448
448
|
type: "static";
|
|
449
449
|
productIds: string[];
|
|
@@ -537,7 +537,7 @@ export declare const categoryFirestoreSchema: z.ZodObject<{
|
|
|
537
537
|
brandCountry?: string | undefined;
|
|
538
538
|
brandFounded?: number | undefined;
|
|
539
539
|
brandBannerImage?: string | undefined;
|
|
540
|
-
|
|
540
|
+
bundlePrice?: number | undefined;
|
|
541
541
|
bundleQueryRule?: {
|
|
542
542
|
type: "static";
|
|
543
543
|
productIds: string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./firestore";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { auditTimestampsShape, firestoreDateSchema,
|
|
3
|
+
import { auditTimestampsShape, firestoreDateSchema, rupeesSchema } from "../../../schemas/firestore-helpers";
|
|
4
4
|
// ─── Firestore document schema (W2) ───────────────────────────────────────────
|
|
5
5
|
// Mirrors CategoryDocument + nested types in ./firestore.ts.
|
|
6
6
|
// Registered into SCHEMAS.firestore.categories.
|
|
@@ -78,7 +78,7 @@ export const categoryFirestoreSchema = z.object({
|
|
|
78
78
|
brandFounded: z.number().int().optional(),
|
|
79
79
|
brandBannerImage: z.string().optional(),
|
|
80
80
|
bundleKind: z.enum(["special", "brand"]).optional(),
|
|
81
|
-
|
|
81
|
+
bundlePrice: rupeesSchema.optional(),
|
|
82
82
|
bundleQueryRule: bundleQueryRuleSchema.optional(),
|
|
83
83
|
bundleStockStatus: z.enum(["in_stock", "out_of_stock"]).optional(),
|
|
84
84
|
bundleQueryResolvedAt: firestoreDateSchema.optional(),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkout Value OTP Actions (appkit) — Tier PP.
|
|
3
|
+
*
|
|
4
|
+
* OTP gate for placing a checkout whose total is at/above
|
|
5
|
+
* `siteSettings.payment.otpCheckoutThreshold` (skipped for COD). A distinct
|
|
6
|
+
* purpose from `checkout-actions.ts`'s third-party shipping consent OTP —
|
|
7
|
+
* same crypto primitives, separate Firestore namespace and copy.
|
|
8
|
+
*/
|
|
9
|
+
/** Sends a checkout-value OTP to the buyer's registered email. Returns masked email so the UI can confirm which inbox to check. */
|
|
10
|
+
export declare function sendCheckoutValueOtp(userId: string, userEmail: string): Promise<{
|
|
11
|
+
maskedEmail: string;
|
|
12
|
+
}>;
|
|
13
|
+
/** Verifies the 6-digit checkout-value OTP and marks the Firestore record verified. */
|
|
14
|
+
export declare function verifyCheckoutValueOtp(userId: string, code: string): Promise<void>;
|
|
15
|
+
/** Whether the buyer has a currently-verified checkout-value OTP on file. */
|
|
16
|
+
export declare function isCheckoutValueOtpVerified(userId: string): Promise<boolean>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkout Value OTP Actions (appkit) — Tier PP.
|
|
3
|
+
*
|
|
4
|
+
* OTP gate for placing a checkout whose total is at/above
|
|
5
|
+
* `siteSettings.payment.otpCheckoutThreshold` (skipped for COD). A distinct
|
|
6
|
+
* purpose from `checkout-actions.ts`'s third-party shipping consent OTP —
|
|
7
|
+
* same crypto primitives, separate Firestore namespace and copy.
|
|
8
|
+
*/
|
|
9
|
+
import { timingSafeEqual } from "crypto";
|
|
10
|
+
import { ValidationError } from "../../../errors";
|
|
11
|
+
import { serverLogger } from "../../../monitoring";
|
|
12
|
+
import { sendEmail } from "../../contact/email";
|
|
13
|
+
import { getAdminDb } from "../../../providers/db-firebase";
|
|
14
|
+
import { resolveDate } from "../../../utils";
|
|
15
|
+
import { CHECKOUT_VALUE_OTP_EXPIRY_MS, CHECKOUT_VALUE_OTP_MAX_ATTEMPTS, hashOtp, generateOtpCode, checkoutValueOtpRef, enforceCheckoutValueOtpRateLimit, } from "../../auth/checkout-value-otp";
|
|
16
|
+
/** Sends a checkout-value OTP to the buyer's registered email. Returns masked email so the UI can confirm which inbox to check. */
|
|
17
|
+
export async function sendCheckoutValueOtp(userId, userEmail) {
|
|
18
|
+
const db = getAdminDb();
|
|
19
|
+
await enforceCheckoutValueOtpRateLimit(db, userId);
|
|
20
|
+
const code = generateOtpCode();
|
|
21
|
+
const codeHash = hashOtp(code);
|
|
22
|
+
const expiresAt = new Date(Date.now() + CHECKOUT_VALUE_OTP_EXPIRY_MS);
|
|
23
|
+
await checkoutValueOtpRef(db, userId).set({
|
|
24
|
+
codeHash,
|
|
25
|
+
expiresAt,
|
|
26
|
+
attempts: 0,
|
|
27
|
+
verified: false,
|
|
28
|
+
createdAt: new Date(),
|
|
29
|
+
});
|
|
30
|
+
const siteName = process.env.NEXT_PUBLIC_SITE_NAME || "LetItRip";
|
|
31
|
+
const [local, domain] = userEmail.split("@");
|
|
32
|
+
const maskedEmail = domain
|
|
33
|
+
? `${local.length <= 2 ? "*".repeat(local.length) : local[0] + "*".repeat(local.length - 2) + local[local.length - 1]}@${domain}`
|
|
34
|
+
: "***";
|
|
35
|
+
await sendEmail({
|
|
36
|
+
to: userEmail,
|
|
37
|
+
subject: `${siteName}: Verify your order`,
|
|
38
|
+
html: `
|
|
39
|
+
<div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:24px">
|
|
40
|
+
<h2 style="margin-bottom:8px">Verify Your Order</h2>
|
|
41
|
+
<p style="color:#555">Your cart total requires verification before checkout. Enter this code to continue:</p>
|
|
42
|
+
<div style="font-size:36px;font-weight:bold;letter-spacing:8px;text-align:center;margin:24px 0;padding:16px;background:#f3f4f6;border-radius:8px">${code}</div>
|
|
43
|
+
<p style="color:#888;font-size:12px">This code expires in 10 minutes. If you did not request this, please ignore this email.</p>
|
|
44
|
+
</div>
|
|
45
|
+
`,
|
|
46
|
+
});
|
|
47
|
+
serverLogger.info(`Checkout value OTP sent: uid=${userId}`);
|
|
48
|
+
return { maskedEmail };
|
|
49
|
+
}
|
|
50
|
+
/** Verifies the 6-digit checkout-value OTP and marks the Firestore record verified. */
|
|
51
|
+
export async function verifyCheckoutValueOtp(userId, code) {
|
|
52
|
+
const db = getAdminDb();
|
|
53
|
+
const ref = checkoutValueOtpRef(db, userId);
|
|
54
|
+
const snap = await ref.get();
|
|
55
|
+
if (!snap.exists) {
|
|
56
|
+
throw new ValidationError("No verification code found. Please request a new code.");
|
|
57
|
+
}
|
|
58
|
+
const otpDoc = snap.data();
|
|
59
|
+
if (otpDoc.verified)
|
|
60
|
+
return;
|
|
61
|
+
if (otpDoc.attempts >= CHECKOUT_VALUE_OTP_MAX_ATTEMPTS) {
|
|
62
|
+
throw new ValidationError("Too many failed attempts. Please request a new code.");
|
|
63
|
+
}
|
|
64
|
+
if (Date.now() > (resolveDate(otpDoc.expiresAt)?.getTime() ?? 0)) {
|
|
65
|
+
throw new ValidationError("Code expired. Please request a new one.");
|
|
66
|
+
}
|
|
67
|
+
const inputHash = hashOtp(code);
|
|
68
|
+
if (!timingSafeEqual(Buffer.from(inputHash, "hex"), Buffer.from(otpDoc.codeHash, "hex"))) {
|
|
69
|
+
await ref.update({ attempts: otpDoc.attempts + 1 });
|
|
70
|
+
throw new ValidationError("Invalid code. Please check and try again.");
|
|
71
|
+
}
|
|
72
|
+
await ref.update({ verified: true, verifiedAt: new Date() });
|
|
73
|
+
serverLogger.info(`Checkout value OTP verified: uid=${userId}`);
|
|
74
|
+
}
|
|
75
|
+
/** Whether the buyer has a currently-verified checkout-value OTP on file. */
|
|
76
|
+
export async function isCheckoutValueOtpVerified(userId) {
|
|
77
|
+
const db = getAdminDb();
|
|
78
|
+
const snap = await checkoutValueOtpRef(db, userId).get();
|
|
79
|
+
if (!snap.exists)
|
|
80
|
+
return false;
|
|
81
|
+
const otpDoc = snap.data();
|
|
82
|
+
return otpDoc.verified === true;
|
|
83
|
+
}
|
|
@@ -21,7 +21,7 @@ export type FailedPaymentDocument = {
|
|
|
21
21
|
uid: string;
|
|
22
22
|
gatewayOrderId?: string;
|
|
23
23
|
gatewayPaymentId?: string;
|
|
24
|
-
/** Amount in
|
|
24
|
+
/** Amount in decimal rupees. */
|
|
25
25
|
amountRs?: number;
|
|
26
26
|
addressId?: string;
|
|
27
27
|
reason: FailedPaymentReason;
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
export { ClassifiedListView } from "./ClassifiedListView";
|
|
2
|
-
export type { ClassifiedListViewProps } from "./ClassifiedListView";
|
|
3
|
-
export { ClassifiedIndexListing } from "./ClassifiedIndexListing";
|
|
4
|
-
export type { ClassifiedIndexListingProps } from "./ClassifiedIndexListing";
|
|
5
1
|
export { ClassifiedFilters } from "./ClassifiedFilters";
|
|
6
2
|
export type { ClassifiedFiltersProps } from "./ClassifiedFilters";
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
export { DigitalCodesListView } from "./DigitalCodesListView";
|
|
2
|
-
export type { DigitalCodesListViewProps } from "./DigitalCodesListView";
|
|
3
|
-
export { DigitalCodesIndexListing } from "./DigitalCodesIndexListing";
|
|
4
|
-
export type { DigitalCodesIndexListingProps } from "./DigitalCodesIndexListing";
|
|
5
1
|
export { DigitalCodeFilters } from "./DigitalCodeFilters";
|
|
6
2
|
export type { DigitalCodeFiltersProps } from "./DigitalCodeFilters";
|
|
@@ -348,7 +348,7 @@ export declare const spinPrizeSchema: z.ZodObject<{
|
|
|
348
348
|
isActive: boolean;
|
|
349
349
|
couponId?: string | undefined;
|
|
350
350
|
}>;
|
|
351
|
-
/** Lottery slot schema — client-safe shape (no
|
|
351
|
+
/** Lottery slot schema — client-safe shape (no price/weight sent to clients). */
|
|
352
352
|
export declare const lotterySlotClientSchema: z.ZodObject<{
|
|
353
353
|
slotNumber: z.ZodNumber;
|
|
354
354
|
name: z.ZodString;
|
|
@@ -77,7 +77,7 @@ export const spinPrizeSchema = z.object({
|
|
|
77
77
|
weight: z.number(),
|
|
78
78
|
isActive: z.boolean(),
|
|
79
79
|
});
|
|
80
|
-
/** Lottery slot schema — client-safe shape (no
|
|
80
|
+
/** Lottery slot schema — client-safe shape (no price/weight sent to clients). */
|
|
81
81
|
export const lotterySlotClientSchema = z.object({
|
|
82
82
|
slotNumber: z.number().int().min(1),
|
|
83
83
|
name: z.string(),
|
|
@@ -13,5 +13,8 @@ export interface BrandsSectionProps {
|
|
|
13
13
|
featuredOnly?: boolean;
|
|
14
14
|
byCountry?: string;
|
|
15
15
|
};
|
|
16
|
+
autoScroll?: boolean;
|
|
17
|
+
scrollInterval?: number;
|
|
18
|
+
loop?: boolean;
|
|
16
19
|
}
|
|
17
|
-
export declare function BrandsSection({ title, subtitle, limit, viewMoreHref, viewMoreLabel, className, initialItems, cta, filters, }: BrandsSectionProps): import("react").JSX.Element | null;
|
|
20
|
+
export declare function BrandsSection({ title, subtitle, limit, viewMoreHref, viewMoreLabel, className, initialItems, cta, filters, autoScroll, scrollInterval, loop, }: BrandsSectionProps): import("react").JSX.Element | null;
|
|
@@ -29,7 +29,7 @@ function BrandLogo({ brand }) {
|
|
|
29
29
|
const initial = brand.name[0]?.toUpperCase() ?? "?";
|
|
30
30
|
return (_jsxs(Link, { href: ROUTES.PUBLIC.CATEGORY_DETAIL(brand.slug), className: "flex h-32 w-36 flex-col items-center justify-center gap-[var(--appkit-space-2)] rounded-xl border border-zinc-200 bg-[var(--appkit-color-surface)] p-[var(--appkit-space-3)] shadow-sm transition-all hover:border-primary-300 hover:shadow-md border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] md:h-40", children: [iconSrc || coverImage ? (_jsx(Image, { src: iconSrc ?? coverImage, alt: brand.name, width: 64, height: 64, className: "h-16 w-16 rounded object-contain" })) : (_jsx(Row, { textWeight: "bold", textSize: "sm", className: "h-16 w-16 bg-primary-100 text-primary-700 dark:bg-primary-900 dark:text-primary-300", align: "center", justify: "center", rounded: "lg", children: initial })), _jsx(Text, { className: "w-full truncate", color: "muted", size: "xs", weight: "medium", align: "start", children: brand.name })] }));
|
|
31
31
|
}
|
|
32
|
-
export function BrandsSection({ title = "Top Brands", subtitle, limit = 12, viewMoreHref, viewMoreLabel = "All brands →", className = "", initialItems, cta, filters, }) {
|
|
32
|
+
export function BrandsSection({ title = "Top Brands", subtitle, limit = 12, viewMoreHref, viewMoreLabel = "All brands →", className = "", initialItems, cta, filters, autoScroll = true, scrollInterval = 4000, loop = true, }) {
|
|
33
33
|
const themed = { textPrimary: THEMED_TEXT_PRIMARY };
|
|
34
34
|
const { data: allBrands = [], isLoading } = useTopBrands(limit, { initialData: initialItems });
|
|
35
35
|
const [activeFilter, setActiveFilter] = useState("all");
|
|
@@ -42,5 +42,5 @@ export function BrandsSection({ title = "Top Brands", subtitle, limit = 12, view
|
|
|
42
42
|
});
|
|
43
43
|
if (!isLoading && allBrands.length === 0)
|
|
44
44
|
return null;
|
|
45
|
-
return (_jsx(Section, { className: `${className}`, surface: "subtle", paddingY: "y-3xl", paddingX: "x-md", children: _jsxs(Div, { className: "mx-auto max-w-7xl", children: [_jsxs(Row, { className: "mb-6", align: "center", justify: "between", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: themed.textPrimary, size: "2xl", mdSize: "3xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { variant: "secondary", className: "mt-1", size: "sm", children: subtitle }))] }), !cta && viewMoreHref && (_jsx(Link, { href: viewMoreHref, className: "text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-primary)] hover:underline", children: viewMoreLabel }))] }), showFeaturedChip && !isLoading && (_jsxs(Row, { wrap: true, gap: "sm", className: "mb-4", children: [_jsx(BrandFilterChip, { label: "All", active: activeFilter === "all", onClick: () => setActiveFilter("all") }), _jsx(BrandFilterChip, { label: "Featured", active: activeFilter === "featured", onClick: () => setActiveFilter(activeFilter === "featured" ? "all" : "featured") })] })), isLoading ? (_jsx(Div, { layout: "flex", gap: "3", className: `${__O.hidden}`, children: Array.from({ length: 8 }).map((_, i) => (_jsx(Div, { className: "h-32 w-36 flex-none animate-pulse md:h-40", surface: "subtle", rounded: "xl" }, i))) })) : (_jsx(HorizontalScroller, { items: brands, renderItem: (brand) => _jsx(BrandLogo, { brand: brand }), keyExtractor: (brand) => brand.id, gap: 12, showArrows: true, showScrollbar: false,
|
|
45
|
+
return (_jsx(Section, { className: `${className}`, surface: "subtle", paddingY: "y-3xl", paddingX: "x-md", children: _jsxs(Div, { className: "mx-auto max-w-7xl", children: [_jsxs(Row, { className: "mb-6", align: "center", justify: "between", children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 2, className: themed.textPrimary, size: "2xl", mdSize: "3xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { variant: "secondary", className: "mt-1", size: "sm", children: subtitle }))] }), !cta && viewMoreHref && (_jsx(Link, { href: viewMoreHref, className: "text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-primary)] hover:underline", children: viewMoreLabel }))] }), showFeaturedChip && !isLoading && (_jsxs(Row, { wrap: true, gap: "sm", className: "mb-4", children: [_jsx(BrandFilterChip, { label: "All", active: activeFilter === "all", onClick: () => setActiveFilter("all") }), _jsx(BrandFilterChip, { label: "Featured", active: activeFilter === "featured", onClick: () => setActiveFilter(activeFilter === "featured" ? "all" : "featured") })] })), isLoading ? (_jsx(Div, { layout: "flex", gap: "3", className: `${__O.hidden}`, children: Array.from({ length: 8 }).map((_, i) => (_jsx(Div, { className: "h-32 w-36 flex-none animate-pulse md:h-40", surface: "subtle", rounded: "xl" }, i))) })) : (_jsx(HorizontalScroller, { items: brands, renderItem: (brand) => _jsx(BrandLogo, { brand: brand }), keyExtractor: (brand) => brand.id, gap: 12, showArrows: true, showScrollbar: false, autoScroll: autoScroll, autoScrollInterval: scrollInterval, pauseOnHover: true, loop: loop })), cta && !isLoading && (_jsx(Div, { className: "mt-6 text-left", children: _jsx(Link, { href: cta.href, className: CTA_CLASSES[cta.variant], children: cta.label }) }))] }) }));
|
|
46
46
|
}
|
|
@@ -55,16 +55,16 @@ function SectionHeader({ title }) {
|
|
|
55
55
|
return (_jsx(Div, { className: "mb-6", children: _jsx(Heading, { level: 2, className: themed.textPrimary, children: title }) }));
|
|
56
56
|
}
|
|
57
57
|
export function CustomCardsSection(config) {
|
|
58
|
-
const { title, layout, columns = 3, cards, autoScroll, scrollIntervalMs } = config;
|
|
58
|
+
const { title, layout, columns = 3, cards, autoScroll, scrollIntervalMs, loop = true } = config;
|
|
59
59
|
if (!cards?.length)
|
|
60
60
|
return null;
|
|
61
61
|
// autoScroll: wrap all cards in SectionCarousel (client carousel)
|
|
62
62
|
if (autoScroll) {
|
|
63
|
-
return (_jsx(Section, { padding: "y-3xl", surface: "muted", children: _jsx(Div, { className: CLS_CONTAINER, children: _jsx(SectionCarousel, { title: title ?? "", items: cards, renderItem: (card) => _jsx(CardItem, { card: card }), keyExtractor: (card) => card.id, autoScroll: true, autoScrollInterval: scrollIntervalMs ?? 3500, perView: { base: 1, sm: 2, md: columns } }) }) }));
|
|
63
|
+
return (_jsx(Section, { padding: "y-3xl", surface: "muted", children: _jsx(Div, { className: CLS_CONTAINER, children: _jsx(SectionCarousel, { title: title ?? "", items: cards, renderItem: (card) => _jsx(CardItem, { card: card }), keyExtractor: (card) => card.id, autoScroll: true, autoScrollInterval: scrollIntervalMs ?? 3500, loop: loop, perView: { base: 1, sm: 2, md: columns } }) }) }));
|
|
64
64
|
}
|
|
65
65
|
// Row layout: horizontal scroller
|
|
66
66
|
if (layout === "row") {
|
|
67
|
-
return (_jsx(Section, { padding: "y-3xl", surface: "muted", children: _jsxs(Div, { className: CLS_CONTAINER, children: [_jsx(SectionHeader, { title: title }), _jsx(HorizontalScroller, { gap: 16, showArrows: true, snapToItems: true, loop:
|
|
67
|
+
return (_jsx(Section, { padding: "y-3xl", surface: "muted", children: _jsxs(Div, { className: CLS_CONTAINER, children: [_jsx(SectionHeader, { title: title }), _jsx(HorizontalScroller, { gap: 16, showArrows: true, snapToItems: true, loop: loop, items: cards, keyExtractor: (card) => card.id, renderItem: (card) => (_jsx(Div, { className: "w-72 flex-shrink-0", children: _jsx(CardItem, { card: card }) })) })] }) }));
|
|
68
68
|
}
|
|
69
69
|
// Masonry layout: CSS columns
|
|
70
70
|
if (layout === "masonry") {
|
|
@@ -9,5 +9,8 @@ export interface CustomerReviewsSectionProps<T = unknown> {
|
|
|
9
9
|
isLoading?: boolean;
|
|
10
10
|
keyExtractor?: (item: T) => string;
|
|
11
11
|
className?: string;
|
|
12
|
+
autoScroll?: boolean;
|
|
13
|
+
scrollInterval?: number;
|
|
14
|
+
loop?: boolean;
|
|
12
15
|
}
|
|
13
|
-
export declare function CustomerReviewsSection<T = unknown>({ title, subtitle, items, renderItem, viewMoreHref, viewMoreLabel, isLoading, keyExtractor, className, }: CustomerReviewsSectionProps<T>): React.JSX.Element | null;
|
|
16
|
+
export declare function CustomerReviewsSection<T = unknown>({ title, subtitle, items, renderItem, viewMoreHref, viewMoreLabel, isLoading, keyExtractor, className, autoScroll, scrollInterval, loop, }: CustomerReviewsSectionProps<T>): React.JSX.Element | null;
|
|
@@ -10,12 +10,12 @@ const __O = {
|
|
|
10
10
|
hidden: "overflow-hidden",
|
|
11
11
|
};
|
|
12
12
|
// --- Section -----------------------------------------------------------------
|
|
13
|
-
export function CustomerReviewsSection({ title, subtitle, items, renderItem, viewMoreHref, viewMoreLabel = "See all reviews", isLoading = false, keyExtractor, className = "", }) {
|
|
13
|
+
export function CustomerReviewsSection({ title, subtitle, items, renderItem, viewMoreHref, viewMoreLabel = "See all reviews", isLoading = false, keyExtractor, className = "", autoScroll = true, scrollInterval = 4500, loop = true, }) {
|
|
14
14
|
const themed = { textPrimary: THEMED_TEXT_PRIMARY, textSecondary: THEMED_TEXT_SECONDARY };
|
|
15
15
|
if (isLoading) {
|
|
16
16
|
return (_jsx(Section, { className: `${__P.p8} ${className}`, surface: "muted", children: _jsxs(Div, { className: "w-full max-w-7xl mx-auto", children: [_jsx(Div, { className: `h-8 ${skeleton.base} mb-8 max-w-xs mx-auto` }), _jsx(Div, { layout: "flex", gap: "6", className: `${__O.hidden}`, children: [...Array(3)].map((_, i) => (_jsx(Div, { className: `${skeleton.card} h-[clamp(180px,26vh,260px)] min-w-[clamp(150px,18vw,260px)] max-w-[clamp(240px,36vw,380px)] flex-none` }, i))) })] }) }));
|
|
17
17
|
}
|
|
18
18
|
if (items.length === 0)
|
|
19
19
|
return null;
|
|
20
|
-
return (_jsx(Section, { className: `${className}`, surface: "muted", padding: "y-3xl", children: _jsxs(Div, { className: "w-full max-w-7xl mx-auto md:px-[2rem]", padding: "x-md", children: [_jsxs(Div, { className: "text-left mb-10", children: [_jsx(Heading, { level: 2, className: `${themed.textPrimary} mb-3`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `${themed.textSecondary}`, size: "base", children: subtitle }))] }), _jsx(HorizontalScroller, { items: items, renderItem: (item) => renderItem(item), perView: CAROUSEL_PER_VIEW.reviews, gap: 24, autoScroll:
|
|
20
|
+
return (_jsx(Section, { className: `${className}`, surface: "muted", padding: "y-3xl", children: _jsxs(Div, { className: "w-full max-w-7xl mx-auto md:px-[2rem]", padding: "x-md", children: [_jsxs(Div, { className: "text-left mb-10", children: [_jsx(Heading, { level: 2, className: `${themed.textPrimary} mb-3`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `${themed.textSecondary}`, size: "base", children: subtitle }))] }), _jsx(HorizontalScroller, { items: items, renderItem: (item) => renderItem(item), perView: CAROUSEL_PER_VIEW.reviews, gap: 24, autoScroll: autoScroll, autoScrollInterval: scrollInterval, pauseOnHover: true, snapToItems: true, showArrows: true, keyExtractor: keyExtractor, loop: loop }), viewMoreHref && (_jsx(Div, { className: "text-left mt-8", children: _jsx(TextLink, { href: viewMoreHref, className: "text-primary hover:text-primary/80", size: "sm", weight: "medium", children: viewMoreLabel }) }))] }) }));
|
|
21
21
|
}
|
|
@@ -8,5 +8,8 @@ export interface EventsSectionProps {
|
|
|
8
8
|
limit?: number;
|
|
9
9
|
className?: string;
|
|
10
10
|
initialItems?: EventItem[];
|
|
11
|
+
autoScroll?: boolean;
|
|
12
|
+
scrollInterval?: number;
|
|
13
|
+
loop?: boolean;
|
|
11
14
|
}
|
|
12
|
-
export declare function EventsSection({ title, description, viewMoreHref, viewMoreLabel, limit, className, initialItems, }: EventsSectionProps): React.JSX.Element;
|
|
15
|
+
export declare function EventsSection({ title, description, viewMoreHref, viewMoreLabel, limit, className, initialItems, autoScroll, scrollInterval, loop, }: EventsSectionProps): React.JSX.Element;
|
|
@@ -4,7 +4,7 @@ import { SectionCarousel } from "./SectionCarousel";
|
|
|
4
4
|
import { useHomepageEvents } from "../hooks/useHomepageEvents";
|
|
5
5
|
import { EventCard } from "../../events/components/EventCard";
|
|
6
6
|
import { CAROUSEL_PER_VIEW } from "../constants/carousel-per-view";
|
|
7
|
-
export function EventsSection({ title = "Events & Offers", description, viewMoreHref, viewMoreLabel = "View all events →", limit = 6, className = "", initialItems, }) {
|
|
7
|
+
export function EventsSection({ title = "Events & Offers", description, viewMoreHref, viewMoreLabel = "View all events →", limit = 6, className = "", initialItems, autoScroll = false, scrollInterval = 5000, loop = true, }) {
|
|
8
8
|
const { data: items = [], isLoading } = useHomepageEvents(limit, { initialData: initialItems });
|
|
9
|
-
return (_jsx(SectionCarousel, { title: title, description: description, pillLabel: "Events & Offers", headingVariant: "editorial", viewMoreHref: viewMoreHref, viewMoreLabel: viewMoreLabel, items: items, isLoading: isLoading, skeletonCount: 3, perView: CAROUSEL_PER_VIEW.events, gap: 16, keyExtractor: (event) => event.id, renderItem: (event) => (_jsx(EventCard, { event: event })), className: className }));
|
|
9
|
+
return (_jsx(SectionCarousel, { title: title, description: description, pillLabel: "Events & Offers", headingVariant: "editorial", viewMoreHref: viewMoreHref, viewMoreLabel: viewMoreLabel, items: items, isLoading: isLoading, skeletonCount: 3, perView: CAROUSEL_PER_VIEW.events, gap: 16, autoScroll: autoScroll, autoScrollInterval: scrollInterval, loop: loop, keyExtractor: (event) => event.id, renderItem: (event) => (_jsx(EventCard, { event: event })), className: className }));
|
|
10
10
|
}
|
|
@@ -11,5 +11,6 @@ export interface FeaturedAuctionsSectionProps {
|
|
|
11
11
|
rows?: number;
|
|
12
12
|
autoScroll?: boolean;
|
|
13
13
|
scrollInterval?: number;
|
|
14
|
+
loop?: boolean;
|
|
14
15
|
}
|
|
15
|
-
export declare function FeaturedAuctionsSection({ title, description, viewMoreHref, viewMoreLabel, className, filterByBrand, initialItems, rows, autoScroll, scrollInterval, }: FeaturedAuctionsSectionProps): React.JSX.Element;
|
|
16
|
+
export declare function FeaturedAuctionsSection({ title, description, viewMoreHref, viewMoreLabel, className, filterByBrand, initialItems, rows, autoScroll, scrollInterval, loop, }: FeaturedAuctionsSectionProps): React.JSX.Element;
|