@mohasinac/appkit 4.53.2 → 4.54.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/.build-stamp.json +3 -3
- package/dist/_internal/server/features/auth/capabilities.js +7 -5
- package/dist/_internal/server/features/checkout/actions.d.ts +22 -6
- package/dist/_internal/server/features/checkout/actions.js +96 -51
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/checkout/supplier-identity.js +28 -6
- package/dist/_internal/server/features/orders/adapters.js +1 -3
- package/dist/_internal/server/features/products/listing-tab-counts.js +81 -25
- package/dist/_internal/server/features/search/index-build/sources.js +43 -2
- package/dist/_internal/server/features/site-settings/adapters.js +1 -1
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +0 -1
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +2 -5
- package/dist/_internal/server/jobs/core/jobRunners.js +0 -10
- package/dist/_internal/server/jobs/core/onOrderCreate.js +10 -104
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +0 -2
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +0 -1
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +0 -1
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +0 -1
- package/dist/_internal/server/notifications/channel-health.d.ts +7 -3
- package/dist/_internal/server/notifications/channel-health.js +2 -2
- package/dist/_internal/server/notifications/send-guard.d.ts +1 -1
- package/dist/_internal/server/notifications/send-guard.js +2 -4
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +128 -28
- package/dist/_internal/shared/checkout/order-math.d.ts +1 -1
- package/dist/_internal/shared/checkout/order-math.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/checkout/config.d.ts +0 -2
- package/dist/_internal/shared/features/checkout/config.js +0 -2
- package/dist/_internal/shared/features/messaging/config.d.ts +7 -5
- package/dist/_internal/shared/features/messaging/config.js +1 -4
- package/dist/_internal/shared/features/site-settings/fees.d.ts +0 -2
- package/dist/_internal/shared/features/site-settings/fees.js +0 -2
- package/dist/_internal/shared/features/site-settings/supplier-of-record.d.ts +56 -0
- package/dist/_internal/shared/features/site-settings/supplier-of-record.js +57 -0
- package/dist/_internal/shared/fees/calculator.d.ts +0 -8
- package/dist/_internal/shared/fees/calculator.js +0 -7
- package/dist/_internal/shared/listing-types/tiers.d.ts +94 -0
- package/dist/_internal/shared/listing-types/tiers.js +150 -0
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +25 -4
- package/dist/client.js +36 -5
- package/dist/constants/api-endpoints.d.ts +21 -15
- package/dist/constants/api-endpoints.js +7 -8
- package/dist/constants/field-names.d.ts +1 -0
- package/dist/constants/field-names.js +1 -0
- package/dist/constants/notification-types.d.ts +1 -1
- package/dist/constants/notification-types.js +1 -1
- package/dist/core/integration-keys.d.ts +5 -5
- package/dist/core/integration-keys.js +21 -10
- package/dist/features/about/components/FeesView.js +0 -6
- package/dist/features/about/components/GuidesHubView.js +15 -2
- package/dist/features/account/components/NotificationPreferencesPanel.js +3 -4
- package/dist/features/account/components/UserOrdersView.js +26 -7
- package/dist/features/account/types/index.d.ts +0 -2
- package/dist/features/addresses/utils/postal-autofill.d.ts +39 -0
- package/dist/features/addresses/utils/postal-autofill.js +54 -0
- package/dist/features/admin/actions/notification-actions.d.ts +2 -8
- package/dist/features/admin/actions/notification-actions.js +9 -104
- package/dist/features/admin/components/AdminGuideHubView.js +1 -8
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +0 -2
- package/dist/features/admin/components/AdminSectionsView.js +3 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +22 -68
- package/dist/features/admin/components/AdminStoreEditorView.js +72 -34
- package/dist/features/admin/components/OwnerQuickActions.d.ts +29 -0
- package/dist/features/admin/components/OwnerQuickActions.js +142 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +13 -4
- package/dist/features/admin/components/sections/icon-options.d.ts +21 -0
- package/dist/features/admin/components/sections/icon-options.js +23 -0
- package/dist/features/admin/components/sections/sectionTemplates.js +4 -1
- package/dist/features/admin/constants/site-settings-tabs.d.ts +7 -12
- package/dist/features/admin/constants/site-settings-tabs.js +6 -12
- package/dist/features/admin/repository/site-settings.repository.js +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.js +4 -1
- package/dist/features/admin/schemas/admin-user-form.d.ts +0 -61
- package/dist/features/admin/schemas/admin-user-form.js +3 -44
- package/dist/features/admin/schemas/firestore.d.ts +28 -54
- package/dist/features/admin/schemas/firestore.js +40 -18
- package/dist/features/auctions/components/AuctionDetailPageView.js +4 -3
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -2
- package/dist/features/auth/checkout-value-otp.d.ts +1 -1
- package/dist/features/auth/checkout-value-otp.js +1 -1
- package/dist/features/auth/permissions/constants.d.ts +29 -2
- package/dist/features/auth/permissions/constants.js +67 -1
- package/dist/features/blog/components/BlogFeaturedCard.d.ts +11 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +9 -2
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/components/CartGroupLineRow.js +2 -1
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +0 -2
- package/dist/features/cart/components/CartPriceBreakdown.js +1 -1
- package/dist/features/cart/components/StoreAddonsPicker.d.ts +2 -5
- package/dist/features/cart/components/StoreAddonsPicker.js +4 -5
- package/dist/features/cart/hooks/useAddToCart.js +10 -5
- package/dist/features/cart/repository/cart.repository.js +1 -2
- package/dist/features/cart/schemas/firestore.d.ts +1 -2
- package/dist/features/cart/utils/pending-ops.d.ts +11 -1
- package/dist/features/cart/utils/pending-ops.js +14 -2
- package/dist/features/categories/components/BrandDetailPageView.js +2 -1
- package/dist/features/categories/components/BundleDetailView.js +2 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +2 -1
- package/dist/features/categories/components/CategoryGrid.d.ts +11 -1
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +10 -5
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +2 -88
- package/dist/features/classified/components/ClassifiedDetailPageView.js +2 -1
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +2 -1
- package/dist/features/events/components/EventCard.d.ts +11 -1
- package/dist/features/events/components/EventCard.js +9 -2
- package/dist/features/grouped/components/GroupedListingDetailView.js +3 -1
- package/dist/features/homepage/components/CTABannerSection.d.ts +3 -1
- package/dist/features/homepage/components/CTABannerSection.js +6 -3
- package/dist/features/homepage/components/HeroCarousel.js +8 -6
- package/dist/features/homepage/components/MarketplaceHomepageView.js +33 -7
- package/dist/features/homepage/components/SectionCarousel.js +13 -5
- package/dist/features/homepage/components/SecurityHighlightsSection.d.ts +8 -3
- package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
- package/dist/features/homepage/components/StatsCounterSection.d.ts +9 -4
- package/dist/features/homepage/components/StatsCounterSection.js +2 -2
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.d.ts +18 -4
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/WelcomeSection.d.ts +13 -2
- package/dist/features/homepage/components/WelcomeSection.js +3 -3
- package/dist/features/homepage/components/WhatsAppCommunitySection.d.ts +28 -0
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +42 -6
- package/dist/features/homepage/components/WhatsAppGlyph.d.ts +20 -0
- package/dist/features/homepage/components/WhatsAppGlyph.js +20 -0
- package/dist/features/homepage/constants/hero-carousel-styles.d.ts +8 -6
- package/dist/features/homepage/constants/hero-carousel-styles.js +8 -6
- package/dist/features/homepage/constants/section-copy.d.ts +12 -10
- package/dist/features/homepage/constants/section-copy.js +28 -6
- package/dist/features/homepage/constants/stat-icons.d.ts +12 -0
- package/dist/features/homepage/constants/stat-icons.js +17 -0
- package/dist/features/homepage/constants/trust-icon-aliases.d.ts +8 -0
- package/dist/features/homepage/constants/trust-icon-aliases.js +75 -0
- package/dist/features/homepage/lib/section-defaults.d.ts +16 -1
- package/dist/features/homepage/lib/section-defaults.js +24 -4
- package/dist/features/homepage/lib/section-renderer.js +48 -8
- package/dist/features/homepage/schemas/firestore.d.ts +18 -1
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BottomActions.d.ts +1 -0
- package/dist/features/layout/BottomActions.js +330 -0
- package/dist/features/layout/BottomChrome.d.ts +45 -0
- package/dist/features/layout/BottomChrome.js +5 -17
- package/dist/features/layout/SideActionDock.js +36 -13
- package/dist/features/layout/index.d.ts +2 -7
- package/dist/features/layout/index.js +7 -7
- package/dist/features/layout/useIsDesktop.d.ts +36 -0
- package/dist/features/layout/useIsDesktop.js +48 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +2 -1
- package/dist/features/orders/actions/refund-actions.js +0 -1
- package/dist/features/orders/components/OrderAddonBadges.d.ts +1 -3
- package/dist/features/orders/components/OrderAddonBadges.js +3 -4
- package/dist/features/orders/components/OrderPaymentSummary.js +15 -2
- package/dist/features/orders/components/YourPurchaseStrip.d.ts +24 -0
- package/dist/features/orders/components/YourPurchaseStrip.js +77 -0
- package/dist/features/orders/components/index.d.ts +2 -1
- package/dist/features/orders/components/index.js +1 -1
- package/dist/features/orders/repository/orders.repository.d.ts +0 -8
- package/dist/features/orders/repository/orders.repository.js +0 -2
- package/dist/features/orders/schemas/firestore.d.ts +17 -9
- package/dist/features/orders/types/index.d.ts +2 -5
- package/dist/features/orders/utils/order-announcement-message.d.ts +18 -0
- package/dist/features/orders/utils/order-announcement-message.js +16 -0
- package/dist/features/orders/utils/payment-proof-message.d.ts +20 -0
- package/dist/features/orders/utils/payment-proof-message.js +17 -0
- package/dist/features/parts/components/PartDetailPageView.js +96 -1
- package/dist/features/parts/schemas/firestore.d.ts +247 -0
- package/dist/features/parts/schemas/firestore.js +6 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +11 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +10 -3
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -3
- package/dist/features/products/api/[id]/route.js +8 -1
- package/dist/features/products/api/route.js +16 -4
- package/dist/features/products/components/AvailabilityScopeHint.js +1 -1
- package/dist/features/products/components/InteractiveProductCard.d.ts +7 -1
- package/dist/features/products/components/InteractiveProductCard.js +16 -4
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +11 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +9 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +11 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +9 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +27 -2
- package/dist/features/products/components/ProductGrid.d.ts +14 -1
- package/dist/features/products/components/ProductGrid.js +22 -5
- package/dist/features/products/components/ProductsIndexListing.js +2 -2
- package/dist/features/reviews/api/[id]/route.js +83 -23
- package/dist/features/reviews/components/PurchaseReviewAffordance.d.ts +6 -0
- package/dist/features/reviews/components/PurchaseReviewAffordance.js +42 -0
- package/dist/features/reviews/components/ReviewFormDrawer.d.ts +34 -0
- package/dist/features/reviews/components/ReviewFormDrawer.js +127 -0
- package/dist/features/reviews/components/index.d.ts +4 -0
- package/dist/features/reviews/components/index.js +2 -0
- package/dist/features/scams/schemas/index.d.ts +10 -10
- package/dist/features/search/action-index/settings-entries.js +0 -9
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +49 -3
- package/dist/features/seller/components/SellerPayoutSettingsView.js +30 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +17 -1
- package/dist/features/seller/hooks/useStoreListingEntitlements.d.ts +8 -0
- package/dist/features/seller/hooks/useStoreListingEntitlements.js +70 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +1 -6
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +1 -10
- package/dist/features/store-extensions/schemas/firestore.d.ts +1 -17
- package/dist/features/store-extensions/schemas/firestore.js +0 -10
- package/dist/features/stores/components/InteractiveStoreCard.d.ts +11 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +9 -2
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +0 -1
- package/dist/features/stores/components/StoreGuideHubView.js +2 -8
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -6
- package/dist/features/stores/components/index.d.ts +0 -2
- package/dist/features/stores/components/index.js +0 -1
- package/dist/features/stores/repository/store.repository.d.ts +1 -26
- package/dist/features/stores/repository/store.repository.js +5 -60
- package/dist/features/stores/schemas/firestore.d.ts +6 -25
- package/dist/features/stores/schemas/firestore.js +6 -3
- package/dist/features/stores/schemas/index.d.ts +1 -87
- package/dist/features/stores/schemas/index.js +10 -15
- package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -48
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +0 -40
- package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +0 -16
- package/dist/features/tester/seed-data/authored/selling__seller-guide.js +1 -1
- package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +0 -79
- package/dist/features/tester/seed-data/authored/selling__seller-orders.js +1 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +415 -69
- package/dist/index.d.ts +20 -32
- package/dist/index.js +34 -43
- package/dist/next/routing/route-map.d.ts +2 -8
- package/dist/next/routing/route-map.js +21 -4
- package/dist/providers/db-firebase/base.repository.d.ts +1 -1
- package/dist/providers/db-firebase/base.repository.js +1 -1
- package/dist/providers/payment-razorpay/index.d.ts +125 -0
- package/dist/providers/payment-razorpay/index.js +232 -0
- package/dist/providers/payment-razorpay/signature.d.ts +53 -0
- package/dist/providers/payment-razorpay/signature.js +71 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +98 -0
- package/dist/providers/shipping-shiprocket/index.js +356 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +3 -0
- package/dist/react/hooks/useCanSeePrices.d.ts +0 -27
- package/dist/react/hooks/useCanSeePrices.js +25 -0
- package/dist/repositories/index.d.ts +1 -1
- package/dist/repositories/index.js +1 -1
- package/dist/schemas/registry.d.ts +10 -115
- package/dist/schemas/registry.js +1 -2
- package/dist/security/pii-encrypt.js +1 -1
- package/dist/seed/_helpers/category-forest.js +27 -0
- package/dist/seed/_helpers/category-parts-glossary-map.js +1816 -88
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +13399 -3019
- package/dist/seed/carousel-slides-seed-data.js +47 -10
- package/dist/seed/categories-seed-data.js +48 -6
- package/dist/seed/faq-seed-data.js +2 -2
- package/dist/seed/homepage-sections-seed-data.js +286 -54
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +1 -1
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +1 -2
- package/dist/seed/model-composition-seed-data.js +6 -8
- package/dist/seed/part-glossary/chunk0.d.ts +9 -0
- package/dist/seed/part-glossary/chunk0.js +35448 -0
- package/dist/seed/part-glossary/chunk1.d.ts +9 -0
- package/dist/seed/part-glossary/chunk1.js +40494 -0
- package/dist/seed/part-glossary/chunk2.d.ts +9 -0
- package/dist/seed/part-glossary/chunk2.js +51242 -0
- package/dist/seed/part-glossary/chunk3.d.ts +9 -0
- package/dist/seed/part-glossary/chunk3.js +53337 -0
- package/dist/seed/part-glossary/chunk4.d.ts +9 -0
- package/dist/seed/part-glossary/chunk4.js +51454 -0
- package/dist/seed/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +23 -47483
- package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
- package/dist/seed/products-catalogue-seed-data.js +63936 -13803
- package/dist/seed/site-settings-seed-data.js +34 -35
- package/dist/seed/store-extensions-seed-data.d.ts +1 -2
- package/dist/seed/store-extensions-seed-data.js +1 -23
- package/dist/seed/stores-seed-data.js +0 -1
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +1 -1
- package/dist/server.d.ts +8 -10
- package/dist/server.js +16 -22
- package/dist/styles.css +392 -43
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -1
- package/dist/tokens/themes/default-light.js +2 -1
- package/dist/tokens/tokens.css +6 -2
- package/dist/ui/components/Button.d.ts +11 -0
- package/dist/ui/components/Button.js +11 -0
- package/dist/ui/components/Button.style.css +29 -0
- package/dist/ui/components/CarouselNav.d.ts +57 -0
- package/dist/ui/components/CarouselNav.js +25 -0
- package/dist/ui/components/CarouselNav.style.css +265 -0
- package/dist/ui/components/GatedPrice.js +30 -3
- package/dist/ui/components/GatedPrice.style.css +43 -40
- package/dist/ui/components/HorizontalScroller.d.ts +12 -1
- package/dist/ui/components/HorizontalScroller.js +43 -3
- package/dist/ui/components/ImageMosaic.d.ts +8 -1
- package/dist/ui/components/ImageMosaic.js +3 -2
- package/dist/ui/components/ImageMosaic.style.css +22 -0
- package/dist/ui/components/Layout.style.css +6 -0
- package/dist/ui/components/Semantic.d.ts +3 -2
- package/dist/ui/components/Semantic.js +1 -0
- package/dist/ui/components/Typography.d.ts +2 -0
- package/dist/ui/components/Typography.js +2 -0
- package/dist/ui/components/Typography.style.css +19 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.js +4 -0
- package/package.json +3 -2
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +0 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +0 -172
- package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +0 -35
- package/dist/_internal/server/jobs/core/whatsappNotify.js +0 -140
- package/dist/features/admin/components/AdminWhatsAppGuideView.d.ts +0 -2
- package/dist/features/admin/components/AdminWhatsAppGuideView.js +0 -35
- package/dist/features/orders/components/MarketplaceOrderCard.d.ts +0 -36
- package/dist/features/orders/components/MarketplaceOrderCard.js +0 -57
- package/dist/features/stores/components/StoreWhatsAppGuideView.d.ts +0 -3
- package/dist/features/stores/components/StoreWhatsAppGuideView.js +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.js +0 -38
- package/dist/features/whatsapp-bot/api/webhook/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/webhook/route.js +0 -43
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +0 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +0 -270
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.d.ts +0 -9
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +0 -7
- package/dist/features/whatsapp-bot/components/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/components/index.js +0 -2
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +0 -14
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +0 -17
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +0 -52
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +0 -283
- package/dist/features/whatsapp-bot/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/index.js +0 -3
- package/dist/features/whatsapp-bot/manifest.d.ts +0 -2
- package/dist/features/whatsapp-bot/manifest.js +0 -13
- package/dist/features/whatsapp-bot/messages/en.json +0 -7
- package/dist/features/whatsapp-bot/server.d.ts +0 -7
- package/dist/features/whatsapp-bot/server.js +0 -7
- package/dist/features/whatsapp-bot/types/index.d.ts +0 -126
- package/dist/features/whatsapp-bot/types/index.js +0 -1
|
@@ -17,14 +17,14 @@ export { AppLayoutShell } from "./AppLayoutShell.js";
|
|
|
17
17
|
export { BottomActionsProvider, useBottomActionsContext, } from "./BottomActionsContext.js";
|
|
18
18
|
export { useBottomActions } from "./hooks/useBottomActions.js";
|
|
19
19
|
export { useFormBottomActions } from "./hooks/useFormBottomActions.js";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* rendering the same actions — the component it resolves to is
|
|
25
|
-
* `SideActionDock`.
|
|
20
|
+
/*
|
|
21
|
+
* The two presentations of one control. `AppLayoutShell` mounts both and
|
|
22
|
+
* `useIsDesktop` lets exactly one render — do not mount either directly, or a
|
|
23
|
+
* page gets two toolbars publishing into the same context.
|
|
26
24
|
*/
|
|
27
|
-
export { default as
|
|
25
|
+
export { default as SideActionDock } from "./SideActionDock.js";
|
|
26
|
+
export { default as BottomActions } from "./BottomActions.js";
|
|
27
|
+
export { useIsDesktop, DESKTOP_QUERY } from "./useIsDesktop.js";
|
|
28
28
|
export { ctaAnchorProps, CTA_ANCHOR_ATTR } from "./cta-anchor.js";
|
|
29
29
|
export { BottomChrome } from "./BottomChrome.js";
|
|
30
30
|
export { BottomNavbar } from "./BottomNavbar.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The line at which the layout stops being a phone.
|
|
3
|
+
*
|
|
4
|
+
* 64rem is Tailwind's `lg` — deliberately the same breakpoint `BottomNavbar`
|
|
5
|
+
* disappears at, so every decision that depends on "is there a tab bar at the
|
|
6
|
+
* bottom of this screen" flips at one place.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DESKTOP_QUERY = "(min-width: 64rem)";
|
|
9
|
+
/**
|
|
10
|
+
* `true` at `lg` and up.
|
|
11
|
+
*
|
|
12
|
+
* ── 🛑 WHY A HOOK AND NOT A `lg:` CLASS ────────────────────────────────────
|
|
13
|
+
*
|
|
14
|
+
* Three callers need the breakpoint as a VALUE, not as styling:
|
|
15
|
+
*
|
|
16
|
+
* - `BottomChrome` must know which CSS variable to publish — a media query
|
|
17
|
+
* can move the box but cannot tell a `ResizeObserver` which end of the
|
|
18
|
+
* screen it landed at.
|
|
19
|
+
* - `SideActionDock` and `BottomActions` are the two halves of one control
|
|
20
|
+
* and must never both be mounted: two toolbars reading the same context,
|
|
21
|
+
* both `fixed`, both dispatching the same callbacks. Hiding one with
|
|
22
|
+
* `display:none` would still mount it, still run its observers, and still
|
|
23
|
+
* let a stray `:focus` land inside an invisible bar.
|
|
24
|
+
*
|
|
25
|
+
* And the class form is actively unsafe here. Both Tailwind configs set
|
|
26
|
+
* `important: true`, so a `lg:` override and its unprefixed base tie on
|
|
27
|
+
* specificity AND on `!important` — a media query adds no specificity — and
|
|
28
|
+
* the winner is decided by EMISSION ORDER in the built CSS, which is invisible
|
|
29
|
+
* from the call site. That is exactly how `BottomChrome` ended up anchored to
|
|
30
|
+
* both edges at once and published an 801px phantom bar (see its header).
|
|
31
|
+
*
|
|
32
|
+
* SSR renders the mobile branch, because that is the branch that is correct
|
|
33
|
+
* when nothing is known: a phone that briefly gets the dock has lost its only
|
|
34
|
+
* CTA, while a desktop that briefly gets the bar has a bar.
|
|
35
|
+
*/
|
|
36
|
+
export declare function useIsDesktop(): boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The line at which the layout stops being a phone.
|
|
5
|
+
*
|
|
6
|
+
* 64rem is Tailwind's `lg` — deliberately the same breakpoint `BottomNavbar`
|
|
7
|
+
* disappears at, so every decision that depends on "is there a tab bar at the
|
|
8
|
+
* bottom of this screen" flips at one place.
|
|
9
|
+
*/
|
|
10
|
+
export const DESKTOP_QUERY = "(min-width: 64rem)";
|
|
11
|
+
/**
|
|
12
|
+
* `true` at `lg` and up.
|
|
13
|
+
*
|
|
14
|
+
* ── 🛑 WHY A HOOK AND NOT A `lg:` CLASS ────────────────────────────────────
|
|
15
|
+
*
|
|
16
|
+
* Three callers need the breakpoint as a VALUE, not as styling:
|
|
17
|
+
*
|
|
18
|
+
* - `BottomChrome` must know which CSS variable to publish — a media query
|
|
19
|
+
* can move the box but cannot tell a `ResizeObserver` which end of the
|
|
20
|
+
* screen it landed at.
|
|
21
|
+
* - `SideActionDock` and `BottomActions` are the two halves of one control
|
|
22
|
+
* and must never both be mounted: two toolbars reading the same context,
|
|
23
|
+
* both `fixed`, both dispatching the same callbacks. Hiding one with
|
|
24
|
+
* `display:none` would still mount it, still run its observers, and still
|
|
25
|
+
* let a stray `:focus` land inside an invisible bar.
|
|
26
|
+
*
|
|
27
|
+
* And the class form is actively unsafe here. Both Tailwind configs set
|
|
28
|
+
* `important: true`, so a `lg:` override and its unprefixed base tie on
|
|
29
|
+
* specificity AND on `!important` — a media query adds no specificity — and
|
|
30
|
+
* the winner is decided by EMISSION ORDER in the built CSS, which is invisible
|
|
31
|
+
* from the call site. That is exactly how `BottomChrome` ended up anchored to
|
|
32
|
+
* both edges at once and published an 801px phantom bar (see its header).
|
|
33
|
+
*
|
|
34
|
+
* SSR renders the mobile branch, because that is the branch that is correct
|
|
35
|
+
* when nothing is known: a phone that briefly gets the dock has lost its only
|
|
36
|
+
* CTA, while a desktop that briefly gets the bar has a bar.
|
|
37
|
+
*/
|
|
38
|
+
export function useIsDesktop() {
|
|
39
|
+
const [isDesktop, setIsDesktop] = useState(false);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const mq = window.matchMedia(DESKTOP_QUERY);
|
|
42
|
+
const sync = () => setIsDesktop(mq.matches);
|
|
43
|
+
sync();
|
|
44
|
+
mq.addEventListener("change", sync);
|
|
45
|
+
return () => mq.removeEventListener("change", sync);
|
|
46
|
+
}, []);
|
|
47
|
+
return isDesktop;
|
|
48
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import Link from "next/link.js";
|
|
3
|
+
import { OwnerQuickActions } from "../../../features/admin/components/OwnerQuickActions.js";
|
|
3
4
|
import { getLiveItemForDetail } from "../../../_internal/server/features/live/data.js";
|
|
4
5
|
const CLS_BREADCRUMB_LINK = "hover:text-primary-600 dark:hover:text-primary-400 transition-colors";
|
|
5
6
|
const CLS_LIVE_ITEM_BADGE = "inline-block rounded-full bg-lime-100 dark:bg-lime-900/30 px-[var(--appkit-space-2-5)] py-[var(--appkit-space-0-5)] text-lime-700 dark:text-lime-300";
|
|
@@ -78,5 +79,5 @@ export async function LiveItemDetailPageView({ slug, initialProduct, renderActio
|
|
|
78
79
|
price: price ?? undefined,
|
|
79
80
|
storeId: typeof p.storeId === "string" ? p.storeId : undefined,
|
|
80
81
|
storeName: storeName ?? undefined,
|
|
81
|
-
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.LIVE), className: CLS_BREADCRUMB_LINK, children: "Live" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => _jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title }), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_ITEM_BADGE, children: "Live Item" }), meta?.vendorVerified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Verified Seller" })), meta?.cites && (_jsxs(Span, { color: "warning", surface: "warning-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: ["CITES: ", meta.cites] }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title }), meta?.species && (_jsxs(Text, { className: "italic mt-1", color: "muted", size: "sm", children: [meta.species, meta.sex && meta.sex !== "n/a" && ` · ${meta.sex}`, meta.ageMonths !== undefined && ` · ${meta.ageMonths}mo`] }))] }), price !== null && (_jsx(Text, { size: "2xl", weight: "bold", color: "primary", children: _jsx(GatedPrice, { children: formatCurrency(price, currency) }) })), jurisdictions.length > 0 && (_jsxs(Div, { className: CLS_WARN_BOX, children: [_jsx(Text, { className: CLS_WARN_TITLE, children: "Delivery restrictions" }), _jsxs(Text, { className: CLS_WARN_BODY, children: ["This item can only be shipped to: ", jurisdictions.join(", ")] })] })), transport && (_jsxs(Div, { textSize: "sm", border: "subtle", surface: "muted", padding: "md", rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Transport" }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)]", children: ["Method: ", transport.method, transport.handlingFee !== undefined && (_jsx(PricesOnly, { children: ` · Handling: ${formatCurrency(transport.handlingFee, "INR")}` })), transport.insuranceIncluded && " · Insurance included"] })] })), meta?.careInfo && (_jsxs(Div, { textSize: "sm", border: "subtle", surface: "muted", padding: "md", rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Care information" }), _jsx(Text, { className: "mt-1 text-[var(--appkit-color-text-muted)]", children: meta.careInfo })] })), 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, { border: "subtle", rounded: "xl", surface: "muted", padding: "md", 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 })] }), 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" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(SpecTable, { rows: specs })) : undefined, reviewsContent: _jsx(ReviewsListingPanel, { source: { kind: "product", productId: product.id }, stateMode: "local", context: "listing", initialData: initialReviews, emptyLabel: "No reviews yet \u2014 be the first to review this product." }), customTabs: toCustomSectionTabs(p.customSections) })), renderBuyBar: () => _jsx(Div, { id: "live-item-buy-bar", children: renderActions?.(product) }), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand, storeLabel: storeName ?? undefined })] })) }), _jsx(ListingBottomActions, { listingType: "live", anchorId: "live-item-buy-bar", price: price, currency: currency })] })] }));
|
|
82
|
+
} }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Nav, { "aria-label": "Breadcrumb", layout: "flex-wrap", gap: "2xs", textSize: "xs", color: "muted", children: [_jsx(Link, { href: String(ROUTES.HOME), className: CLS_BREADCRUMB_LINK, children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.LIVE), className: CLS_BREADCRUMB_LINK, children: "Live" }), category && (_jsxs(_Fragment, { children: [_jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(category)), className: CLS_BREADCRUMB_LINK, children: categoryName || category })] })), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => _jsx(ProductGalleryClient, { images: images, video: productVideo, productName: title }), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_LIVE_ITEM_BADGE, children: "Live Item" }), meta?.vendorVerified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: "Verified Seller" })), meta?.cites && (_jsxs(Span, { color: "warning", surface: "warning-surface", size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", children: ["CITES: ", meta.cites] }))] }), _jsx(OwnerQuickActions, { resource: "PRODUCT", placement: "detail", recordLabel: String(p.title ?? p.slug ?? p.id), storeId: p.storeId ? String(p.storeId) : undefined, editHref: String(ROUTES.STORE.PRODUCTS_EDIT(String(p.id))) }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title }), meta?.species && (_jsxs(Text, { className: "italic mt-1", color: "muted", size: "sm", children: [meta.species, meta.sex && meta.sex !== "n/a" && ` · ${meta.sex}`, meta.ageMonths !== undefined && ` · ${meta.ageMonths}mo`] }))] }), price !== null && (_jsx(Text, { size: "2xl", weight: "bold", color: "primary", children: _jsx(GatedPrice, { children: formatCurrency(price, currency) }) })), jurisdictions.length > 0 && (_jsxs(Div, { className: CLS_WARN_BOX, children: [_jsx(Text, { className: CLS_WARN_TITLE, children: "Delivery restrictions" }), _jsxs(Text, { className: CLS_WARN_BODY, children: ["This item can only be shipped to: ", jurisdictions.join(", ")] })] })), transport && (_jsxs(Div, { textSize: "sm", border: "subtle", surface: "muted", padding: "md", rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Transport" }), _jsxs(Text, { className: "text-[var(--appkit-color-text-muted)]", children: ["Method: ", transport.method, transport.handlingFee !== undefined && (_jsx(PricesOnly, { children: ` · Handling: ${formatCurrency(transport.handlingFee, "INR")}` })), transport.insuranceIncluded && " · Insurance included"] })] })), meta?.careInfo && (_jsxs(Div, { textSize: "sm", border: "subtle", surface: "muted", padding: "md", rounded: "lg", children: [_jsx(Text, { weight: "medium", children: "Care information" }), _jsx(Text, { className: "mt-1 text-[var(--appkit-color-text-muted)]", children: meta.careInfo })] })), 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, { border: "subtle", rounded: "xl", surface: "muted", padding: "md", 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 })] }), 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" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(SpecTable, { rows: specs })) : undefined, reviewsContent: _jsx(ReviewsListingPanel, { source: { kind: "product", productId: product.id }, stateMode: "local", context: "listing", initialData: initialReviews, emptyLabel: "No reviews yet \u2014 be the first to review this product." }), customTabs: toCustomSectionTabs(p.customSections) })), renderBuyBar: () => _jsx(Div, { id: "live-item-buy-bar", children: renderActions?.(product) }), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand, storeLabel: storeName ?? undefined })] })) }), _jsx(ListingBottomActions, { listingType: "live", anchorId: "live-item-buy-bar", price: price, currency: currency })] })] }));
|
|
82
83
|
}
|
|
@@ -49,7 +49,6 @@ export async function issuePartialRefund(adminUid, orderId, deductFees, refundNo
|
|
|
49
49
|
: `Your full refund of ₹${grossRefund} is being processed.`,
|
|
50
50
|
relatedId: orderId,
|
|
51
51
|
relatedType: "order",
|
|
52
|
-
orderWhatsappAddonPaid: order.whatsappNotifyAddon === true,
|
|
53
52
|
});
|
|
54
53
|
serverLogger.info("Admin partial refund initiated", {
|
|
55
54
|
adminUid,
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
/**
|
|
3
3
|
* Icon badges for an order's paid add-ons and applied coupon.
|
|
4
4
|
*
|
|
5
|
-
* These are fulfilment instructions, not decoration:
|
|
5
|
+
* These are fulfilment instructions, not decoration: gift wrap tells the
|
|
6
6
|
* status-change notifier to message this buyer, gift wrap tells the packer to
|
|
7
7
|
* wrap the parcel and enclose the message, and either protection changes how a
|
|
8
8
|
* claim is handled. They are recorded on the order (and filterable in the
|
|
@@ -14,8 +14,6 @@ import React from "react";
|
|
|
14
14
|
* at once instead of being wired per screen.
|
|
15
15
|
*/
|
|
16
16
|
export interface OrderAddonBadgesOrder {
|
|
17
|
-
whatsappNotifyAddon?: boolean;
|
|
18
|
-
whatsappNotifyFee?: number;
|
|
19
17
|
giftWrapAddon?: boolean;
|
|
20
18
|
giftWrapFee?: number;
|
|
21
19
|
giftWrapMessage?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Gift,
|
|
3
|
+
import { Gift, ShieldAlert, ShieldCheck, Tag } from "lucide-react";
|
|
4
4
|
import { Row, Span, Stack, Text } from "../../../ui/index.js";
|
|
5
5
|
import { formatCurrency } from "../../../utils/number.formatter.js";
|
|
6
6
|
const CHIP_BASE = "inline-flex items-center gap-[var(--appkit-space-1)] rounded-full px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-[length:var(--appkit-text-xs)] font-medium";
|
|
@@ -15,15 +15,14 @@ function Chip({ icon, label, tone, title, }) {
|
|
|
15
15
|
export function OrderAddonBadges({ order, variant = "compact", showCoupon = true, currency = "INR", className = "", }) {
|
|
16
16
|
const money = (v) => (typeof v === "number" && v > 0 ? formatCurrency(v, currency) : undefined);
|
|
17
17
|
const hasCoupon = showCoupon && !!order.couponCode;
|
|
18
|
-
const hasAny = order.
|
|
19
|
-
order.giftWrapAddon ||
|
|
18
|
+
const hasAny = order.giftWrapAddon ||
|
|
20
19
|
order.shipmentProtectionAddon ||
|
|
21
20
|
order.saleProtectionAddon ||
|
|
22
21
|
hasCoupon;
|
|
23
22
|
if (!hasAny)
|
|
24
23
|
return null;
|
|
25
24
|
const isDetail = variant === "detail";
|
|
26
|
-
return (_jsxs(Stack, { gap: "xs", className: `min-w-0 ${className}`, children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, className: "min-w-0", children: [order.
|
|
25
|
+
return (_jsxs(Stack, { gap: "xs", className: `min-w-0 ${className}`, children: [_jsxs(Row, { gap: "xs", align: "center", wrap: true, className: "min-w-0", children: [order.giftWrapAddon && (_jsx(Chip, { icon: _jsx(Gift, { size: 12 }), label: isDetail && money(order.giftWrapFee) ? `Gift wrap · ${money(order.giftWrapFee)}` : "Gift wrap", tone: "brand", title: "This parcel must be gift-wrapped before dispatch." })), order.shipmentProtectionAddon && (_jsx(Chip, { icon: _jsx(ShieldCheck, { size: 12 }), label: isDetail && money(order.shipmentProtectionFee) ? `Protected · ${money(order.shipmentProtectionFee)}` : "Protected", tone: "info", title: "Shipment protection purchased \u2014 loss or damage in transit is covered, claimed against the held funds." })), order.saleProtectionAddon && (_jsx(Chip, { icon: _jsx(ShieldAlert, { size: 12 }), label: isDetail && money(order.saleProtectionFee) ? `Sale protected · ${money(order.saleProtectionFee)}` : "Sale protected", tone: "info", title: "Sale protection purchased \u2014 if the item is not as described the buyer is refunded, no questions asked." })), hasCoupon && (_jsx(Chip, { icon: _jsx(Tag, { size: 12 }), label: isDetail && money(order.couponDiscount)
|
|
27
26
|
? `${order.couponCode} · −${money(order.couponDiscount)}`
|
|
28
27
|
: order.couponCode, tone: "success", title: `Coupon ${order.couponCode} applied to this order.` }))] }), isDetail && order.giftWrapAddon && order.giftWrapMessage && (_jsxs(Stack, { gap: "xs", className: "min-w-0", children: [_jsx(Text, { size: "xs", color: "muted", weight: "semibold", transform: "uppercase", className: "tracking-wide", children: "Gift message" }), _jsx(Text, { size: "sm", color: "primary", className: "min-w-0 whitespace-pre-wrap break-words", children: order.giftWrapMessage })] }))] }));
|
|
29
28
|
}
|
|
@@ -5,13 +5,26 @@ import { formatCurrency } from "../../../utils/number.formatter.js";
|
|
|
5
5
|
const METHOD_LABEL = {
|
|
6
6
|
manual: "Manual (Cash / UPI)",
|
|
7
7
|
phonepe: "PhonePe",
|
|
8
|
+
razorpay: "Razorpay",
|
|
8
9
|
cod: "Cash on Delivery",
|
|
9
10
|
};
|
|
10
11
|
function legacyFallback(order) {
|
|
11
12
|
if (!order.paymentMethod)
|
|
12
13
|
return null;
|
|
14
|
+
/*
|
|
15
|
+
* Only reached by orders written before `paymentRecord` existed, so the
|
|
16
|
+
* gateway behind a bare `paymentMethod: "online"` has to be inferred.
|
|
17
|
+
*
|
|
18
|
+
* 🛑 It is inferred as RAZORPAY, not PhonePe, and the reason is evidence
|
|
19
|
+
* rather than preference: PhonePe has never processed a payment in any
|
|
20
|
+
* environment — `payment.phonepeEnabled` has been false throughout and
|
|
21
|
+
* every PhonePe credential is still a placeholder — so no `online` order
|
|
22
|
+
* can be its. Every such order predates the Razorpay→PhonePe migration.
|
|
23
|
+
* Orders placed from now on carry a real `paymentRecord` naming the live
|
|
24
|
+
* gateway, so this inference never applies to them in either direction.
|
|
25
|
+
*/
|
|
13
26
|
const method = order.paymentMethod === "online"
|
|
14
|
-
? "
|
|
27
|
+
? "razorpay"
|
|
15
28
|
: order.paymentMethod === "cod"
|
|
16
29
|
? "cod"
|
|
17
30
|
: "manual";
|
|
@@ -20,7 +33,7 @@ function legacyFallback(order) {
|
|
|
20
33
|
transactionId: order.paymentTransactionId ?? order.paymentId,
|
|
21
34
|
proofUrl: order.paymentProofUrl,
|
|
22
35
|
amount: order.totalPrice,
|
|
23
|
-
verificationMethod: method === "
|
|
36
|
+
verificationMethod: method === "cod" ? "cod_collection" : method === "manual" ? "manual_review" : "order_status",
|
|
24
37
|
};
|
|
25
38
|
}
|
|
26
39
|
export function OrderPaymentSummary({ order, className = "" }) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface PurchaseContext {
|
|
2
|
+
order: {
|
|
3
|
+
id: string;
|
|
4
|
+
shortRef: string;
|
|
5
|
+
status: string;
|
|
6
|
+
orderDate: string | null;
|
|
7
|
+
trackHref: string;
|
|
8
|
+
detailHref: string;
|
|
9
|
+
} | null;
|
|
10
|
+
review: {
|
|
11
|
+
id: string;
|
|
12
|
+
rating: number;
|
|
13
|
+
status: string;
|
|
14
|
+
} | null;
|
|
15
|
+
windowDays: number;
|
|
16
|
+
}
|
|
17
|
+
export interface YourPurchaseStripProps {
|
|
18
|
+
productId: string;
|
|
19
|
+
/** Opens the review editor. Omit to render the review half as a link only. */
|
|
20
|
+
onEditReview?: (reviewId: string) => void;
|
|
21
|
+
onWriteReview?: () => void;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function YourPurchaseStrip({ productId, onEditReview, onWriteReview, className, }: YourPurchaseStripProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* "You ordered this — track it" and "your review — edit it", on a product page.
|
|
5
|
+
*
|
|
6
|
+
* ── Why this exists ───────────────────────────────────────────────────────
|
|
7
|
+
*
|
|
8
|
+
* A buyer looking at an item they already own had no link to their own order
|
|
9
|
+
* and no link to their own review. Both records exist; nothing connected them
|
|
10
|
+
* to the product page, so the route was: remember you bought it, go to
|
|
11
|
+
* /user/orders, page through, find it.
|
|
12
|
+
*
|
|
13
|
+
* ── Three rules this component is built around ────────────────────────────
|
|
14
|
+
*
|
|
15
|
+
* 🛑 NO MONEY. An order total here would need the guest-price gate, and the
|
|
16
|
+
* strip is signed-in-only by construction — omitting the amount removes the
|
|
17
|
+
* question entirely rather than answering it carefully.
|
|
18
|
+
*
|
|
19
|
+
* 🛑 SAY THE WINDOW. The lookup is bounded to 90 days (see the route: order
|
|
20
|
+
* `items[]` holds objects, so there is no index for "order containing this
|
|
21
|
+
* product"). When nothing is found the copy is "No order in the last 90 days",
|
|
22
|
+
* never "you haven't bought this". A filtered empty result reported as an
|
|
23
|
+
* absolute zero is a lie the buyer cannot check — the same defect
|
|
24
|
+
* `UserOrdersView` carries a long comment about.
|
|
25
|
+
*
|
|
26
|
+
* 🛑 RENDER NOTHING UNTIL RESOLVED. Public product pages are ISR and read no
|
|
27
|
+
* session, so `loading` starts true on every hard load even for signed-in
|
|
28
|
+
* users. Showing the signed-out state first would flash "no order" at someone
|
|
29
|
+
* who has one.
|
|
30
|
+
*
|
|
31
|
+
* @tag domain:orders
|
|
32
|
+
* @tag layer:components
|
|
33
|
+
* @tag access:client
|
|
34
|
+
*/
|
|
35
|
+
import { useApiQuery } from "../../../client/api/useApiQuery.js";
|
|
36
|
+
import { apiClient } from "../../../http/index.js";
|
|
37
|
+
import { useOptionalSession } from "../../../react/contexts/SessionContext.js";
|
|
38
|
+
import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
|
|
39
|
+
import { ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints.js";
|
|
40
|
+
import { ROUTES } from "../../../next/routing/route-map.js";
|
|
41
|
+
import { Button, Div, Row, Span, Stack, Text, TextLink } from "../../../ui/index.js";
|
|
42
|
+
import { Icon } from "../../../ui/components/Icon.js";
|
|
43
|
+
import { formatDate } from "../../../utils/index.js";
|
|
44
|
+
export function YourPurchaseStrip({ productId, onEditReview, onWriteReview, className = "", }) {
|
|
45
|
+
const session = useOptionalSession();
|
|
46
|
+
const signedIn = Boolean(session?.user?.uid);
|
|
47
|
+
const query = useApiQuery({
|
|
48
|
+
queryKey: ["user", "purchases", productId],
|
|
49
|
+
queryFn: async () => {
|
|
50
|
+
const res = await apiClient.get(ACCOUNT_ENDPOINTS.PURCHASE_CONTEXT(productId));
|
|
51
|
+
return (res?.data ?? { order: null, review: null, windowDays: 90 });
|
|
52
|
+
},
|
|
53
|
+
// Only ask once we know there is somebody to ask about.
|
|
54
|
+
enabled: signedIn,
|
|
55
|
+
staleTime: 60000,
|
|
56
|
+
silentBackgroundFailures: true,
|
|
57
|
+
});
|
|
58
|
+
/*
|
|
59
|
+
* A guest, or auth not yet resolved, renders nothing at all. There is no
|
|
60
|
+
* useful signed-out state here: "sign in to see your order" is noise on a
|
|
61
|
+
* page whose primary job is selling the item.
|
|
62
|
+
*/
|
|
63
|
+
if (!session || session.loading || !signedIn)
|
|
64
|
+
return null;
|
|
65
|
+
if (query.isLoading || !query.data)
|
|
66
|
+
return null;
|
|
67
|
+
const { order, review, windowDays } = query.data;
|
|
68
|
+
// Nothing bought and nothing written — stay out of the way entirely.
|
|
69
|
+
if (!order && !review)
|
|
70
|
+
return null;
|
|
71
|
+
return (_jsx(Div, { surface: "muted", rounded: "xl", padding: "md", border: "subtle", className: className, children: _jsxs(Stack, { gap: "sm", children: [order ? (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Icon, { name: "order", size: "sm", tone: "muted" }), _jsxs(Text, { size: "sm", children: ["You ordered this", order.orderDate ? ` on ${formatDate(order.orderDate)}` : "", " \u00B7", " ", _jsxs(Span, { className: "font-mono", children: ["#", order.shortRef] })] })] }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsx(TextLink, { href: order.trackHref, children: ACTIONS.USER["track-order"].label }) }), _jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsx(TextLink, { href: order.detailHref, children: ACTIONS.USER["view-order"].label }) })] })] })) : (
|
|
72
|
+
/*
|
|
73
|
+
* 🛑 Bounded, and it says so. Not "you haven't bought this".
|
|
74
|
+
*/
|
|
75
|
+
_jsxs(Text, { size: "sm", color: "muted", children: ["No order for this item in the last ", windowDays, " days.", " ", _jsx(TextLink, { href: String(ROUTES.USER.ORDERS), children: "See all your orders" })] })), review ? (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Icon, { name: "review", size: "sm", tone: "muted", filled: true }), _jsxs(Text, { size: "sm", children: ["Your review: ", review.rating, "/5", review.status !== "approved" ? ` · ${review.status}` : ""] })] }), onEditReview && (_jsx(Button, { variant: "outline", size: "sm", onClick: () => onEditReview(review.id), children: ACTIONS.REVIEW.edit.label }))] })) : (order &&
|
|
76
|
+
onWriteReview && (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsx(Text, { size: "sm", color: "muted", children: "You have not reviewed this yet." }), _jsx(Button, { variant: "outline", size: "sm", onClick: onWriteReview, children: ACTIONS.REVIEW.write.label })] })))] }) }));
|
|
77
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { OrderCard, OrdersList } from "./OrdersList";
|
|
2
2
|
export { OrderAddonBadges, type OrderAddonBadgesOrder, type OrderAddonBadgesProps, } from "./OrderAddonBadges";
|
|
3
|
-
export { MarketplaceOrderCard, type MarketplaceOrderCardLabels, type MarketplaceOrderCardLinks, type MarketplaceOrderCardOrder, type MarketplaceOrderCardProps, } from "./MarketplaceOrderCard";
|
|
4
3
|
export { OrderFilters, ORDER_FILTER_KEYS, ORDER_ADMIN_SORT_OPTIONS, ORDER_SELLER_SORT_OPTIONS, ORDER_USER_SORT_OPTIONS, getOrderFilterKeys, getOrderSortOptions, } from "./OrderFilters";
|
|
5
4
|
export type { OrderFiltersProps, OrderFilterVariant } from "./OrderFilters";
|
|
6
5
|
export { OrderSiblingPayments } from "./OrderSiblingPayments";
|
|
@@ -13,3 +12,5 @@ export { RefundHistoryTable } from "./RefundHistoryTable";
|
|
|
13
12
|
export type { RefundHistoryTableProps } from "./RefundHistoryTable";
|
|
14
13
|
export { RefundRequestView } from "./RefundRequestView";
|
|
15
14
|
export type { RefundRequestViewProps } from "./RefundRequestView";
|
|
15
|
+
export { YourPurchaseStrip } from "./YourPurchaseStrip";
|
|
16
|
+
export type { YourPurchaseStripProps, PurchaseContext } from "./YourPurchaseStrip";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { OrderCard, OrdersList } from "./OrdersList.js";
|
|
2
2
|
export { OrderAddonBadges, } from "./OrderAddonBadges.js";
|
|
3
|
-
export { MarketplaceOrderCard, } from "./MarketplaceOrderCard.js";
|
|
4
3
|
export { OrderFilters, ORDER_FILTER_KEYS, ORDER_ADMIN_SORT_OPTIONS, ORDER_SELLER_SORT_OPTIONS, ORDER_USER_SORT_OPTIONS, getOrderFilterKeys, getOrderSortOptions, } from "./OrderFilters.js";
|
|
5
4
|
export { OrderSiblingPayments } from "./OrderSiblingPayments.js";
|
|
6
5
|
export { OrderPaymentSummary } from "./OrderPaymentSummary.js";
|
|
7
6
|
export { OrderStatusTimeline } from "./OrderStatusTimeline.js";
|
|
8
7
|
export { RefundHistoryTable } from "./RefundHistoryTable.js";
|
|
9
8
|
export { RefundRequestView } from "./RefundRequestView.js";
|
|
9
|
+
export { YourPurchaseStrip } from "./YourPurchaseStrip.js";
|
|
@@ -156,10 +156,6 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
|
|
|
156
156
|
canFilter: boolean;
|
|
157
157
|
canSort: boolean;
|
|
158
158
|
};
|
|
159
|
-
whatsappNotifyAddon: {
|
|
160
|
-
canFilter: boolean;
|
|
161
|
-
canSort: boolean;
|
|
162
|
-
};
|
|
163
159
|
giftWrapAddon: {
|
|
164
160
|
canFilter: boolean;
|
|
165
161
|
canSort: boolean;
|
|
@@ -280,10 +276,6 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
|
|
|
280
276
|
canFilter: boolean;
|
|
281
277
|
canSort: boolean;
|
|
282
278
|
};
|
|
283
|
-
whatsappNotifyAddon: {
|
|
284
|
-
canFilter: boolean;
|
|
285
|
-
canSort: boolean;
|
|
286
|
-
};
|
|
287
279
|
giftWrapAddon: {
|
|
288
280
|
canFilter: boolean;
|
|
289
281
|
canSort: boolean;
|
|
@@ -722,7 +722,6 @@ OrderRepository.SELLER_SIEVE_FIELDS = {
|
|
|
722
722
|
// Fulfilment flags. Filterable so "which of my orders need gift wrap?" is a
|
|
723
723
|
// query against the orders themselves — the whole point of recording the
|
|
724
724
|
// add-on on the order rather than keeping a side list of who asked for what.
|
|
725
|
-
whatsappNotifyAddon: { canFilter: true, canSort: false },
|
|
726
725
|
giftWrapAddon: { canFilter: true, canSort: false },
|
|
727
726
|
shipmentProtectionAddon: { canFilter: true, canSort: false },
|
|
728
727
|
saleProtectionAddon: { canFilter: true, canSort: false },
|
|
@@ -755,7 +754,6 @@ OrderRepository.ADMIN_SIEVE_FIELDS = {
|
|
|
755
754
|
// Same fulfilment flags as SELLER_SIEVE_FIELDS — admin needs to answer
|
|
756
755
|
// "who opted into WhatsApp updates?" when a status change goes out, without
|
|
757
756
|
// maintaining a parallel tracker.
|
|
758
|
-
whatsappNotifyAddon: { canFilter: true, canSort: false },
|
|
759
757
|
giftWrapAddon: { canFilter: true, canSort: false },
|
|
760
758
|
shipmentProtectionAddon: { canFilter: true, canSort: false },
|
|
761
759
|
saleProtectionAddon: { canFilter: true, canSort: false },
|
|
@@ -304,6 +304,8 @@ export interface OrderRefundEvent {
|
|
|
304
304
|
refundedBy: string;
|
|
305
305
|
/** Set when PhonePe processed the refund. */
|
|
306
306
|
phonepeRefundId?: string;
|
|
307
|
+
/** Set when Razorpay processed the refund (`rfnd_…`). Mutually exclusive with `phonepeRefundId` — one online gateway runs at a time. */
|
|
308
|
+
razorpayRefundId?: string;
|
|
307
309
|
/** Set when refund was processed manually (offline). */
|
|
308
310
|
manualTransactionId?: string;
|
|
309
311
|
/** Proof document URL (via /api/media signed-URL flow). */
|
|
@@ -449,10 +451,6 @@ export interface OrderDocument extends BaseDocument {
|
|
|
449
451
|
codRemainingAmount?: number;
|
|
450
452
|
/** COD handling fee charged to the buyer: max(codHandlingFeeMin, subtotal × codHandlingFeePercent / 100). Only set when paymentMethod === "cod". */
|
|
451
453
|
codHandlingFee?: number;
|
|
452
|
-
/** Buyer opted into WhatsApp order-update messages at checkout (unchecked by default). */
|
|
453
|
-
whatsappNotifyAddon?: boolean;
|
|
454
|
-
/** Fee charged for the WhatsApp addon, decimal rupees — snapshot of siteSettings.commissions.whatsappNotifyFee at order time. */
|
|
455
|
-
whatsappNotifyFee?: number;
|
|
456
454
|
/** Buyer opted into gift wrapping at checkout (unchecked by default). */
|
|
457
455
|
giftWrapAddon?: boolean;
|
|
458
456
|
/** Fee charged for gift wrap, decimal rupees — snapshot of siteSettings.commissions.giftWrapFee at order time. */
|
|
@@ -743,23 +741,33 @@ export interface OrderDocument extends BaseDocument {
|
|
|
743
741
|
/** Set true only when an automatic partial refund (for dropped Razorpay items) failed and needs manual follow-up. */
|
|
744
742
|
refundPending?: boolean;
|
|
745
743
|
}
|
|
746
|
-
export type OrderPaymentRecordMethod = "manual" | "phonepe" | "cod";
|
|
744
|
+
export type OrderPaymentRecordMethod = "manual" | "phonepe" | "razorpay" | "cod";
|
|
747
745
|
export type OrderPaymentVerificationMethod = "manual_review" | "webhook" | "cod_collection" | "order_status";
|
|
748
746
|
export interface OrderPaymentRecord {
|
|
749
747
|
method: OrderPaymentRecordMethod;
|
|
750
|
-
/** UTR (manual) | PhonePe transactionId (
|
|
748
|
+
/** UTR (manual) | PhonePe transactionId / Razorpay `pay_…` (gateway) | collector note/ref (COD). */
|
|
751
749
|
transactionId?: string;
|
|
752
|
-
/** Manual proof upload | COD collection receipt photo (optional) | n/a for
|
|
750
|
+
/** Manual proof upload | COD collection receipt photo (optional) | n/a for a gateway. */
|
|
753
751
|
proofUrl?: string;
|
|
754
752
|
amount: number;
|
|
755
753
|
paidAt?: Date;
|
|
756
|
-
/** Admin/seller uid (manual/COD) | "
|
|
754
|
+
/** Admin/seller uid (manual/COD) | "{gateway}-order-status" or "{gateway}-webhook" (automatic). */
|
|
757
755
|
verifiedBy?: string;
|
|
758
756
|
verificationMethod: OrderPaymentVerificationMethod;
|
|
759
|
-
/**
|
|
757
|
+
/**
|
|
758
|
+
* Gateway audit trail only.
|
|
759
|
+
*
|
|
760
|
+
* `merchantOrderId` is the id this codebase stores as `order.paymentId` and
|
|
761
|
+
* keys every lookup on, whichever gateway is live — PhonePe's own
|
|
762
|
+
* `merchantOrderId`, or Razorpay's `order_…`. The provider-specific fields
|
|
763
|
+
* below record the gateway's extra ids when it has them.
|
|
764
|
+
*/
|
|
760
765
|
gatewayRef?: {
|
|
761
766
|
merchantOrderId?: string;
|
|
762
767
|
phonepeOrderId?: string;
|
|
768
|
+
razorpayOrderId?: string;
|
|
769
|
+
/** Razorpay's payment id (`pay_…`) — the key its refund API needs. */
|
|
770
|
+
razorpayPaymentId?: string;
|
|
763
771
|
transactionId?: string;
|
|
764
772
|
};
|
|
765
773
|
}
|
|
@@ -216,15 +216,12 @@ export interface Order {
|
|
|
216
216
|
/**
|
|
217
217
|
* Paid add-ons the buyer opted into for THIS order (= this store).
|
|
218
218
|
*
|
|
219
|
-
* These are operational flags, not just billing records:
|
|
220
|
-
*
|
|
221
|
-
* WhatsApp message, and `giftWrapAddon`/`shipmentProtectionAddon` are what
|
|
219
|
+
* These are operational flags, not just billing records:
|
|
220
|
+
* `giftWrapAddon`/`shipmentProtectionAddon` are what
|
|
222
221
|
* the packer needs to see before dispatch. They live on the order itself and
|
|
223
222
|
* are filterable (`orders` SIEVE_FIELDS) precisely so nobody has to keep a
|
|
224
223
|
* separate list of who asked for what.
|
|
225
224
|
*/
|
|
226
|
-
whatsappNotifyAddon?: boolean;
|
|
227
|
-
whatsappNotifyFee?: number;
|
|
228
225
|
giftWrapAddon?: boolean;
|
|
229
226
|
giftWrapFee?: number;
|
|
230
227
|
/** The buyer's gift message — the packer has to physically include this. */
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface PurchaseAnnouncementInput {
|
|
2
|
+
buyerName: string;
|
|
3
|
+
firstItemName: string;
|
|
4
|
+
/** 0 if only one item in the order */
|
|
5
|
+
additionalItemCount: number;
|
|
6
|
+
/** Total order amount in decimal rupees */
|
|
7
|
+
totalAmount: number;
|
|
8
|
+
orderId: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Plain-text body for the "New order placed" staff notification row.
|
|
12
|
+
*
|
|
13
|
+
* Originally built for the WhatsApp purchase announcement. That integration
|
|
14
|
+
* was removed 2026-10-20, but the builder survives because its output is now
|
|
15
|
+
* the `adminNotifications` body the admin inbox renders and the daily digest
|
|
16
|
+
* counts — a durable record rather than a per-admin blast.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildPurchaseAnnouncementMessage(input: PurchaseAnnouncementInput): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-text body for the "New order placed" staff notification row.
|
|
3
|
+
*
|
|
4
|
+
* Originally built for the WhatsApp purchase announcement. That integration
|
|
5
|
+
* was removed 2026-10-20, but the builder survives because its output is now
|
|
6
|
+
* the `adminNotifications` body the admin inbox renders and the daily digest
|
|
7
|
+
* counts — a durable record rather than a per-admin blast.
|
|
8
|
+
*/
|
|
9
|
+
export function buildPurchaseAnnouncementMessage(input) {
|
|
10
|
+
const { buyerName, firstItemName, additionalItemCount, totalAmount, orderId } = input;
|
|
11
|
+
const extra = additionalItemCount > 0
|
|
12
|
+
? ` + ${additionalItemCount} more item${additionalItemCount > 1 ? "s" : ""}`
|
|
13
|
+
: "";
|
|
14
|
+
const amount = totalAmount.toLocaleString("en-IN");
|
|
15
|
+
return `🛍️ New order! ${buyerName} purchased ${firstItemName}${extra} for ₹${amount}. Order #${orderId}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PaymentProofReviewMessageInput {
|
|
2
|
+
orderId: string;
|
|
3
|
+
buyerName: string;
|
|
4
|
+
productTitle: string;
|
|
5
|
+
totalAmount: number;
|
|
6
|
+
reviewUrl: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tier PP — message body for the buyer/seller "share for review" `wa.me`
|
|
10
|
+
* link on the order payment page.
|
|
11
|
+
*
|
|
12
|
+
* Pure string builder with no crypto and no network, so it is safe to export
|
|
13
|
+
* from the client-safe barrel. It used to live beside the WhatsApp Cloud API
|
|
14
|
+
* senders in `features/whatsapp-bot/`, isolated into its own file precisely
|
|
15
|
+
* because those siblings carried a top-level `import { createHmac } from
|
|
16
|
+
* "crypto"`. The Cloud API integration was removed 2026-10-20; this builder
|
|
17
|
+
* survived because it feeds an ordinary `wa.me` deep link, which needs no
|
|
18
|
+
* token, no registered number and no Meta billing relationship.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildPaymentProofReviewMessage(input: PaymentProofReviewMessageInput): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier PP — message body for the buyer/seller "share for review" `wa.me`
|
|
3
|
+
* link on the order payment page.
|
|
4
|
+
*
|
|
5
|
+
* Pure string builder with no crypto and no network, so it is safe to export
|
|
6
|
+
* from the client-safe barrel. It used to live beside the WhatsApp Cloud API
|
|
7
|
+
* senders in `features/whatsapp-bot/`, isolated into its own file precisely
|
|
8
|
+
* because those siblings carried a top-level `import { createHmac } from
|
|
9
|
+
* "crypto"`. The Cloud API integration was removed 2026-10-20; this builder
|
|
10
|
+
* survived because it feeds an ordinary `wa.me` deep link, which needs no
|
|
11
|
+
* token, no registered number and no Meta billing relationship.
|
|
12
|
+
*/
|
|
13
|
+
export function buildPaymentProofReviewMessage(input) {
|
|
14
|
+
const { orderId, buyerName, productTitle, totalAmount, reviewUrl } = input;
|
|
15
|
+
const amount = totalAmount.toLocaleString("en-IN");
|
|
16
|
+
return `💳 Payment proof submitted! ${buyerName} uploaded proof for "${productTitle}" (₹${amount}). Order #${orderId}. Please review within 2 hours or it auto-confirms: ${reviewUrl}`;
|
|
17
|
+
}
|