@mohasinac/appkit 4.62.0 → 4.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
- package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
- package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
- package/dist/_internal/server/features/ads/booking.d.ts +118 -0
- package/dist/_internal/server/features/ads/booking.js +326 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +129 -9
- package/dist/_internal/server/features/checkout/actions.js +850 -79
- package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
- package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
- package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
- package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
- package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
- package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
- package/dist/_internal/server/features/dashboard/attention.js +183 -0
- package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
- package/dist/_internal/server/features/dashboard/data.js +82 -0
- package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
- package/dist/_internal/server/features/inventory/reservations.js +273 -0
- package/dist/_internal/server/features/invoicing/allocate.d.ts +63 -0
- package/dist/_internal/server/features/invoicing/allocate.js +162 -0
- package/dist/_internal/server/features/invoicing/credit-note.d.ts +57 -0
- package/dist/_internal/server/features/invoicing/credit-note.js +126 -0
- package/dist/_internal/server/features/invoicing/gstr1.d.ts +74 -0
- package/dist/_internal/server/features/invoicing/gstr1.js +251 -0
- package/dist/_internal/server/features/invoicing/issue.d.ts +96 -0
- package/dist/_internal/server/features/invoicing/issue.js +202 -0
- package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
- package/dist/_internal/server/features/offers/destinations.js +65 -0
- package/dist/_internal/server/features/orders/actions.d.ts +8 -1
- package/dist/_internal/server/features/orders/actions.js +81 -8
- package/dist/_internal/server/features/orders/adapters.js +54 -0
- package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
- package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
- package/dist/_internal/server/features/orders/balance.d.ts +89 -0
- package/dist/_internal/server/features/orders/balance.js +256 -0
- package/dist/_internal/server/features/orders/cancellation-refund.d.ts +15 -9
- package/dist/_internal/server/features/orders/cancellation-refund.js +15 -9
- package/dist/_internal/server/features/points/award.js +46 -4
- package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
- package/dist/_internal/server/features/pricing/actions.js +144 -0
- package/dist/_internal/server/features/refunds/actions.js +26 -0
- package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
- package/dist/_internal/server/features/shipping/book-split.js +130 -0
- package/dist/_internal/server/features/shipping/book.d.ts +61 -0
- package/dist/_internal/server/features/shipping/book.js +176 -0
- package/dist/_internal/server/features/shipping/courier-block.d.ts +69 -0
- package/dist/_internal/server/features/shipping/courier-block.js +264 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +29 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +2 -2
- package/dist/_internal/server/features/stores/adapters.js +65 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +95 -2
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +11 -2
- package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +4 -0
- package/dist/_internal/server/jobs/core/dailyStatusDigest.js +19 -2
- package/dist/_internal/server/jobs/core/index.d.ts +2 -1
- package/dist/_internal/server/jobs/core/index.js +2 -1
- package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
- package/dist/_internal/server/jobs/core/onJobCreated.d.ts +30 -7
- package/dist/_internal/server/jobs/core/onJobCreated.js +78 -45
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +7 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +65 -0
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +33 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
- package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
- package/dist/_internal/server/jobs/core/runJobOnce.d.ts +48 -0
- package/dist/_internal/server/jobs/core/runJobOnce.js +195 -0
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +25 -2
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onOrderStatusChange.js +17 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
- package/dist/_internal/server/notifications/channel-health.d.ts +26 -3
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +296 -0
- package/dist/_internal/shared/checkout/coupon-discount.d.ts +43 -1
- package/dist/_internal/shared/checkout/coupon-discount.js +26 -1
- package/dist/_internal/shared/checkout/order-math.d.ts +174 -0
- package/dist/_internal/shared/checkout/order-math.js +159 -0
- package/dist/_internal/shared/checkout/refundable-base.d.ts +25 -0
- package/dist/_internal/shared/checkout/refundable-base.js +13 -1
- package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
- package/dist/_internal/shared/checkout/rules/index.js +1 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
- package/dist/_internal/shared/checkout/split.d.ts +75 -0
- package/dist/_internal/shared/checkout/split.js +120 -0
- package/dist/_internal/shared/content/disclaimers.d.ts +88 -0
- package/dist/_internal/shared/content/disclaimers.js +217 -0
- package/dist/_internal/shared/content/published-values.d.ts +93 -0
- package/dist/_internal/shared/content/published-values.js +206 -0
- package/dist/_internal/shared/features/admin/integrations.d.ts +139 -0
- package/dist/_internal/shared/features/admin/integrations.js +263 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
- package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
- package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
- package/dist/_internal/shared/features/emi/choice.js +69 -0
- package/dist/_internal/shared/features/emi/group.d.ts +84 -0
- package/dist/_internal/shared/features/emi/group.js +126 -0
- package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
- package/dist/_internal/shared/features/ledger/posting.js +165 -0
- package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
- package/dist/_internal/shared/features/ledger/reports.js +127 -0
- package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
- package/dist/_internal/shared/features/ledger/rules.js +221 -0
- package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
- package/dist/_internal/shared/features/offers/coordination.js +80 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
- package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.d.ts +113 -0
- package/dist/_internal/shared/features/orders/dispute-reasons.js +181 -0
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
- package/dist/_internal/shared/features/orders/refund-copy.js +18 -1
- package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
- package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
- package/dist/_internal/shared/features/points/accepts.d.ts +29 -0
- package/dist/_internal/shared/features/points/accepts.js +49 -0
- package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
- package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
- package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
- package/dist/_internal/shared/features/shipping/parcel.js +139 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.d.ts +91 -0
- package/dist/_internal/shared/features/shipping/shared-purchase.js +108 -0
- package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
- package/dist/_internal/shared/features/site-settings/fees.js +12 -8
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/fees/calculator.d.ts +33 -1
- package/dist/_internal/shared/fees/calculator.js +32 -2
- package/dist/_internal/shared/fees/explain.d.ts +81 -0
- package/dist/_internal/shared/fees/explain.js +101 -0
- package/dist/_internal/shared/history/index.d.ts +1 -1
- package/dist/_internal/shared/history/index.js +1 -1
- package/dist/_internal/shared/history/types.d.ts +7 -1
- package/dist/_internal/shared/history/types.js +25 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.js +43 -0
- package/dist/constants/api-endpoints.d.ts +114 -0
- package/dist/constants/api-endpoints.js +55 -0
- package/dist/constants/field-names.d.ts +42 -0
- package/dist/constants/field-names.js +52 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/shipping.d.ts +45 -0
- package/dist/contracts/shipping.js +15 -0
- package/dist/features/about/components/AboutView.js +1 -1
- package/dist/features/account/components/BuyerAuctionsGuideView.js +4 -1
- package/dist/features/account/components/UserOrdersView.js +47 -35
- package/dist/features/admin/components/AdminCouponEditorView.js +17 -0
- package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
- package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
- package/dist/features/admin/components/AdminInvoicingView.d.ts +2 -0
- package/dist/features/admin/components/AdminInvoicingView.js +65 -0
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +33 -1
- package/dist/features/admin/components/AdminOrderEditorView.js +81 -3
- package/dist/features/admin/components/AdminOrdersGuideView.js +23 -2
- package/dist/features/admin/components/AdminOrdersView.js +86 -5
- package/dist/features/admin/components/OwnerQuickActions.js +24 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +6 -0
- package/dist/features/admin/constants/filter-tabs.js +6 -0
- package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
- package/dist/features/admin/hooks/useAdminListingData.js +16 -0
- package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
- package/dist/features/admin/schemas/firestore.d.ts +62 -0
- package/dist/features/admin/schemas/firestore.js +5 -0
- package/dist/features/ads/schemas/booking-write.d.ts +120 -0
- package/dist/features/ads/schemas/booking-write.js +75 -0
- package/dist/features/ads/schemas/creative-form.d.ts +18 -0
- package/dist/features/ads/schemas/creative-form.js +51 -0
- package/dist/features/ads/schemas/firestore.d.ts +140 -0
- package/dist/features/ads/schemas/firestore.js +109 -0
- package/dist/features/auctions/repository/bid.repository.js +3 -1
- package/dist/features/audit-log/schemas/firestore.d.ts +140 -0
- package/dist/features/audit-log/schemas/firestore.js +89 -0
- package/dist/features/auth/actions/profile-actions.d.ts +69 -1
- package/dist/features/auth/actions/profile-actions.js +62 -1
- package/dist/features/auth/permissions/constants.js +13 -0
- package/dist/features/auth/schemas/firestore.d.ts +16 -2
- package/dist/features/auth/schemas/firestore.js +2 -1
- package/dist/features/blog/actions/blog-actions.d.ts +6 -0
- package/dist/features/blog/actions/blog-actions.js +17 -2
- package/dist/features/blog/api/route.js +4 -1
- package/dist/features/blog/columns/index.js +5 -0
- package/dist/features/blog/components/BlogIndexPageView.js +2 -1
- package/dist/features/blog/repository/blog.repository.d.ts +4 -0
- package/dist/features/blog/repository/blog.repository.js +5 -0
- package/dist/features/blog/schemas/blog-form.d.ts +3 -0
- package/dist/features/blog/schemas/blog-form.js +1 -0
- package/dist/features/blog/schemas/firestore.d.ts +38 -1
- package/dist/features/blog/schemas/firestore.js +23 -0
- package/dist/features/blog/schemas/index.d.ts +6 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +2 -0
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +25 -1
- package/dist/features/cart/components/CartPriceBreakdown.js +29 -6
- package/dist/features/cart/components/PointsTenderPicker.d.ts +61 -0
- package/dist/features/cart/components/PointsTenderPicker.js +15 -0
- package/dist/features/cart/components/StoreAddonsPicker.js +2 -1
- package/dist/features/cart/components/index.d.ts +2 -0
- package/dist/features/cart/components/index.js +1 -0
- package/dist/features/cart/repository/cart.repository.d.ts +33 -0
- package/dist/features/cart/repository/cart.repository.js +47 -0
- package/dist/features/cart/schemas/firestore.d.ts +116 -0
- package/dist/features/contact/email.d.ts +27 -10
- package/dist/features/contact/email.js +20 -3
- package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
- package/dist/features/dashboard/components/DashboardHubView.js +56 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
- package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
- package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +62 -0
- package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +108 -0
- package/dist/features/dispute-reasons/schemas/firestore.d.ts +62 -0
- package/dist/features/dispute-reasons/schemas/firestore.js +40 -0
- package/dist/features/events/components/EventSaleBanner.js +1 -1
- package/dist/features/faq/components/FAQAccordion.d.ts +13 -1
- package/dist/features/faq/components/FAQAccordion.js +29 -4
- package/dist/features/faq/components/FAQPageContent.js +2 -2
- package/dist/features/gateway-events/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +8 -8
- package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
- package/dist/features/inventory/schemas/stock-reservation.js +103 -0
- package/dist/features/invoicing/schemas/firestore.d.ts +112 -0
- package/dist/features/invoicing/schemas/firestore.js +45 -0
- package/dist/features/invoicing/utils/financial-year.d.ts +43 -0
- package/dist/features/invoicing/utils/financial-year.js +53 -0
- package/dist/features/jobs/actions/enqueue-job.js +18 -1
- package/dist/features/jobs/repository/jobs.repository.d.ts +62 -1
- package/dist/features/jobs/repository/jobs.repository.js +84 -1
- package/dist/features/jobs/schemas/firestore.d.ts +80 -0
- package/dist/features/jobs/schemas/firestore.js +37 -0
- package/dist/features/layout/AppLayoutShell.d.ts +9 -1
- package/dist/features/layout/AppLayoutShell.js +12 -4
- package/dist/features/layout/BottomActions.js +2 -1
- package/dist/features/layout/BottomNavbar.d.ts +10 -2
- package/dist/features/layout/SideActionDock.js +52 -2
- package/dist/features/layout/TitleBarLayout.js +13 -4
- package/dist/features/layout/TitleBarLayout.style.css +59 -0
- package/dist/features/layout/useCtaReveal.d.ts +16 -1
- package/dist/features/layout/useCtaReveal.js +17 -26
- package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
- package/dist/features/ledger/repository/journal.repository.js +312 -0
- package/dist/features/ledger/schemas/expenses.d.ts +87 -0
- package/dist/features/ledger/schemas/expenses.js +27 -0
- package/dist/features/ledger/schemas/firestore.d.ts +183 -0
- package/dist/features/ledger/schemas/firestore.js +69 -0
- package/dist/features/lottery/schemas/zod.d.ts +6 -6
- package/dist/features/media/MediaImage.js +22 -1
- package/dist/features/media/upload/ImageUpload.js +1 -1
- package/dist/features/obligations/constants/policies.js +24 -1
- package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
- package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
- package/dist/features/orders/components/OrderPaymentSummary.js +10 -1
- package/dist/features/orders/components/OrderProvenanceCard.d.ts +8 -0
- package/dist/features/orders/components/OrderProvenanceCard.js +185 -0
- package/dist/features/orders/components/RaiseDisputeForm.d.ts +14 -0
- package/dist/features/orders/components/RaiseDisputeForm.js +119 -0
- package/dist/features/orders/components/RefundRequestView.js +19 -1
- package/dist/features/orders/components/index.d.ts +4 -0
- package/dist/features/orders/components/index.js +2 -0
- package/dist/features/orders/constants/order-lane-tabs.d.ts +69 -0
- package/dist/features/orders/constants/order-lane-tabs.js +88 -0
- package/dist/features/orders/repository/orders.repository.d.ts +85 -1
- package/dist/features/orders/repository/orders.repository.js +205 -6
- package/dist/features/orders/schemas/balance.d.ts +40 -0
- package/dist/features/orders/schemas/balance.js +47 -0
- package/dist/features/orders/schemas/firestore.d.ts +398 -1
- package/dist/features/orders/schemas/firestore.js +43 -0
- package/dist/features/orders/schemas/index.d.ts +56 -8
- package/dist/features/orders/schemas/index.js +12 -0
- package/dist/features/orders/types/index.d.ts +47 -0
- package/dist/features/orders/utils/courier-block.d.ts +25 -0
- package/dist/features/orders/utils/courier-block.js +23 -0
- package/dist/features/payment-cases/schemas/firestore.d.ts +26 -1
- package/dist/features/payment-cases/schemas/firestore.js +1 -0
- package/dist/features/payments/repository/payout.repository.js +3 -2
- package/dist/features/payments/schemas/firestore.d.ts +92 -1
- package/dist/features/payments/schemas/firestore.js +23 -0
- package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
- package/dist/features/pricing/components/AdminPricingView.js +157 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/ProductDetailPageView.d.ts +17 -1
- package/dist/features/products/components/ProductDetailPageView.js +2 -2
- package/dist/features/products/schemas/firestore.d.ts +26 -1
- package/dist/features/products/schemas/firestore.js +2 -0
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/promotions/actions/coupon-stacking.d.ts +30 -3
- package/dist/features/promotions/actions/coupon-stacking.js +21 -2
- package/dist/features/promotions/components/CouponCard.js +13 -0
- package/dist/features/promotions/constants/coupon-help.d.ts +2 -2
- package/dist/features/promotions/constants/coupon-help.js +9 -1
- package/dist/features/promotions/schemas/firestore.d.ts +24 -0
- package/dist/features/promotions/schemas/firestore.js +4 -0
- package/dist/features/promotions/types/index.d.ts +19 -1
- package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
- package/dist/features/reviews/repository/reviews.repository.js +16 -0
- package/dist/features/scams/components/ScamProfileView.js +2 -2
- package/dist/features/scams/components/ScamRegistryView.js +2 -2
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +2 -1
- package/dist/features/scams/schemas/firestore.js +2 -1
- package/dist/features/search/action-index/tab-entries.js +1 -1
- package/dist/features/seller/actions/offer-actions.js +56 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +37 -3
- package/dist/features/seller/components/DispatchForm.d.ts +11 -0
- package/dist/features/seller/components/DispatchForm.js +190 -0
- package/dist/features/seller/components/SellerOrdersView.js +221 -27
- package/dist/features/seller/components/index.d.ts +1 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/seller/hooks/useSellerListingData.js +25 -0
- package/dist/features/seller/repository/offer.repository.js +4 -3
- package/dist/features/seller/schemas/firestore.d.ts +23 -2
- package/dist/features/seller/schemas/firestore.js +3 -2
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +61 -4
- package/dist/features/seller/schemas/order-forms.js +41 -8
- package/dist/features/shipments/schemas/firestore.d.ts +25 -0
- package/dist/features/shipments/schemas/validation.d.ts +4 -4
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +82 -0
- package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +145 -0
- package/dist/features/shipping-boxes/schemas/firestore.d.ts +80 -0
- package/dist/features/shipping-boxes/schemas/firestore.js +53 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +2 -2
- package/dist/features/stores/components/StoreOrdersGuideView.js +6 -1
- package/dist/features/stores/repository/store.repository.d.ts +18 -0
- package/dist/features/stores/repository/store.repository.js +27 -1
- package/dist/features/stores/schemas/firestore.d.ts +112 -0
- package/dist/features/stores/schemas/firestore.js +20 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/stores/types/index.d.ts +19 -0
- package/dist/features/support/repository/support.repository.js +72 -6
- package/dist/features/support/schemas/firestore.d.ts +17 -0
- package/dist/features/support/schemas/index.d.ts +8 -8
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +33 -1
- package/dist/next/routing/route-map.d.ts +112 -0
- package/dist/next/routing/route-map.js +63 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +27 -1
- package/dist/providers/shipping-shiprocket/index.js +84 -1
- package/dist/react/contexts/SessionContext.d.ts +17 -1
- package/dist/schemas/registry.d.ts +69 -34
- package/dist/schemas/sieve.d.ts +2 -2
- package/dist/security/pii-schemas.d.ts +1 -1
- package/dist/security/pii-schemas.js +45 -0
- package/dist/server-entry.d.ts +2 -2
- package/dist/server-entry.js +8 -1
- package/dist/server.d.ts +36 -1
- package/dist/server.js +183 -1
- package/dist/styles.css +412 -80
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -0
- package/dist/tokens/themes/default-light.js +1 -0
- package/dist/tokens/themes/required.d.ts +1 -1
- package/dist/tokens/themes/required.js +1 -0
- package/dist/tokens/tokens.css +15 -0
- package/dist/ui/components/Button.d.ts +10 -1
- package/dist/ui/components/Button.js +25 -3
- package/dist/ui/components/Chart.d.ts +63 -0
- package/dist/ui/components/Chart.js +169 -0
- package/dist/ui/components/Chart.style.css +214 -0
- package/dist/ui/components/Disclaimer.d.ts +19 -0
- package/dist/ui/components/Disclaimer.js +83 -0
- package/dist/ui/components/OverflowRow.js +54 -2
- package/dist/ui/components/OverflowRow.style.css +38 -0
- package/dist/ui/components/RichTextEditor.js +99 -8
- package/dist/ui/components/chart-spec.d.ts +68 -0
- package/dist/ui/components/chart-spec.js +140 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/surface-tokens.d.ts +1 -1
- package/dist/ui/components/surface-tokens.js +9 -0
- package/dist/ui/components/tabs-overflow.js +64 -11
- package/dist/ui/components/toolbar-collapse.d.ts +13 -0
- package/dist/ui/components/toolbar-collapse.js +10 -1
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/rich-text/RichText.d.ts +10 -1
- package/dist/ui/rich-text/RichText.js +33 -2
- package/dist/ui/rich-text/RichText.style.css +83 -79
- package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
- package/dist/ui/rich-text/RichTextRenderer.js +34 -2
- package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
- package/dist/ui/rich-text/chart-blocks.js +87 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +1834 -1822
|
@@ -102,7 +102,7 @@ export declare const SITE_SETTINGS_TABS: readonly [{
|
|
|
102
102
|
readonly description: "Which listing types sellers may create, and their defaults.";
|
|
103
103
|
readonly keywords: ["listing types", "auctions on", "enable", "categories"];
|
|
104
104
|
}];
|
|
105
|
-
export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "notifications" | "contact" | "auction" | "seo" | "listings" | "
|
|
105
|
+
export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "notifications" | "contact" | "auction" | "seo" | "listings" | "emi" | "legal" | "appearance" | "gst" | "watermark" | "integrations" | "limits" | "announcement" | "branding" | "themes" | "fees" | "procurement")[];
|
|
106
106
|
/**
|
|
107
107
|
* The union `?tab=` is validated against.
|
|
108
108
|
*
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import { useQuery } from "@tanstack/react-query";
|
|
3
3
|
import { apiClient, ApiClientError } from "../../../http/index.js";
|
|
4
4
|
import { formatCurrency } from "../../../utils/number.formatter.js";
|
|
5
|
+
// The defining module, not a barrel (Root Cause #18). `hasEncPrefix` is a pure
|
|
6
|
+
// string test with no crypto in its import chain, so it is client-safe.
|
|
7
|
+
import { hasEncPrefix } from "../../../security/pii-mask.js";
|
|
5
8
|
function withQueryParams(endpoint, params) {
|
|
6
9
|
const hasQuery = endpoint.includes("?");
|
|
7
10
|
const query = new URLSearchParams(params).toString();
|
|
@@ -50,6 +53,19 @@ export function toRecordArray(value) {
|
|
|
50
53
|
}
|
|
51
54
|
export function toStringValue(value, fallback = "-") {
|
|
52
55
|
if (typeof value === "string") {
|
|
56
|
+
/*
|
|
57
|
+
* 🛑 Ciphertext is not a display value. See the twin in
|
|
58
|
+
* `features/seller/hooks/useSellerListingData.ts` for the full account —
|
|
59
|
+
* the short version is that `mapDoc` does not decrypt, so a route that
|
|
60
|
+
* forgets `revealOrders`/`maskedOrders` hands this a stored `enc:v1:…`
|
|
61
|
+
* blob which is a perfectly ordinary `string` and renders verbatim.
|
|
62
|
+
*
|
|
63
|
+
* `/api/admin/orders` already hit this ("measured live at 3 visible
|
|
64
|
+
* `enc:v1:` strings") and fixed it at the route. This is the backstop for
|
|
65
|
+
* the next one.
|
|
66
|
+
*/
|
|
67
|
+
if (hasEncPrefix(value))
|
|
68
|
+
return fallback;
|
|
53
69
|
return value.trim() || fallback;
|
|
54
70
|
}
|
|
55
71
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
@@ -82,13 +82,13 @@ export declare const lotteryPullSchema: z.ZodObject<{
|
|
|
82
82
|
userPhone: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
|
83
83
|
}, "strip", z.ZodTypeAny, {
|
|
84
84
|
transactionId: string;
|
|
85
|
-
sourceType: "
|
|
85
|
+
sourceType: "product" | "event";
|
|
86
86
|
paymentTime: string;
|
|
87
87
|
purchasedItemNumber: number;
|
|
88
88
|
userPhone?: string | undefined;
|
|
89
89
|
}, {
|
|
90
90
|
transactionId: string;
|
|
91
|
-
sourceType: "
|
|
91
|
+
sourceType: "product" | "event";
|
|
92
92
|
paymentTime: string;
|
|
93
93
|
purchasedItemNumber: number;
|
|
94
94
|
userPhone?: string | undefined;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Covers: notifications, chat rooms, site settings
|
|
4
4
|
*/
|
|
5
5
|
import type { AboutContentDocument } from "../../about/schemas/firestore";
|
|
6
|
+
import type { RateChange } from "../../../_internal/shared/features/pricing/rate-registry";
|
|
6
7
|
export declare const ADMIN_CHECKOUT_BYPASS_FLAG_KEY: "adminCheckoutBypass";
|
|
7
8
|
export declare const NOTIFICATION_TYPE_VALUES: readonly ["order_placed", "order_confirmed", "order_shipped", "order_delivered", "order_cancelled", "bid_placed", "bid_outbid", "bid_won", "bid_lost", "auction_ended", "review_approved", "review_replied", "product_available", "promotion", "system", "welcome", "account_action", "support_ticket_update", "scam_report_update", "offer_received", "offer_responded", "offer_expired", "offer_counter_accepted", "refund_initiated", "prize_won", "prize_reveal_expired", "emi_installment_due_soon", "emi_installment_overdue", "payment_review", "catalogue_images_stale", "message_received"];
|
|
8
9
|
export type NotificationType = (typeof NOTIFICATION_TYPE_VALUES)[number];
|
|
@@ -233,6 +234,18 @@ export type SiteSettingsAdPlacement = {
|
|
|
233
234
|
label: string;
|
|
234
235
|
enabled: boolean;
|
|
235
236
|
reservedHeight: number;
|
|
237
|
+
/**
|
|
238
|
+
* D56 — the flat monthly rate for a self-serve booking of this slot, in
|
|
239
|
+
* rupees. Absent means NOT SOLD: `bookAdSlot` refuses rather than
|
|
240
|
+
* defaulting to zero, because a free booking that looks successful takes
|
|
241
|
+
* the slot, bills nothing, and says nothing about the missing price.
|
|
242
|
+
*
|
|
243
|
+
* 🛑 Editing this does NOT reprice a sold slot. `AdBookingDocument.priceRs`
|
|
244
|
+
* is snapshotted at booking, for the same reason `sourceContext` is
|
|
245
|
+
* written once: the rate is a price somebody agreed to, and re-deriving it
|
|
246
|
+
* later silently rewrites a completed sale.
|
|
247
|
+
*/
|
|
248
|
+
priceRsPerPeriod?: number;
|
|
236
249
|
};
|
|
237
250
|
/** Embedded in siteSettings.adSettings — a type alias, not a collection root. */
|
|
238
251
|
export type SiteSettingsAdInventoryItem = {
|
|
@@ -690,6 +703,36 @@ export interface SiteSettingsDocument extends BaseDocument {
|
|
|
690
703
|
returns: {
|
|
691
704
|
windowDays: number;
|
|
692
705
|
};
|
|
706
|
+
/**
|
|
707
|
+
* The support integration's on/off switch.
|
|
708
|
+
*
|
|
709
|
+
* 🛑 The ONLY new integration flag. The other three the admin page switches
|
|
710
|
+
* already have an authoritative field — `payment.razorpayEnabled`,
|
|
711
|
+
* `messaging.emailEnabled` (which `guardSend` reads), and
|
|
712
|
+
* `shipping.provider`. Adding a parallel `integrationSwitches.*` beside
|
|
713
|
+
* those would be a denormalised mirror that drifts the first time one path
|
|
714
|
+
* writes only one of a pair (Root Cause #42), and the page would then
|
|
715
|
+
* disagree with the code that enforces it. The page is a VIEW over the real
|
|
716
|
+
* fields; this is the one field that did not exist.
|
|
717
|
+
*
|
|
718
|
+
* 🛑 Also not under `siteSettings.integrations` — that key is live and holds
|
|
719
|
+
* analytics/tag IDs (GA, FB Pixel, GTM).
|
|
720
|
+
*
|
|
721
|
+
* OFF hides the WHOLE support surface from BUYERS: no nav entry, no ticket
|
|
722
|
+
* list, no contact form. Staff keep full access, so an open ticket is still
|
|
723
|
+
* workable and the employee pay-per-ticket basis survives.
|
|
724
|
+
*
|
|
725
|
+
* 🛑 A buyer mid-conversation loses sight of their thread. That is the
|
|
726
|
+
* owner's decision, accepted knowingly — and the admin row must SAY it
|
|
727
|
+
* rather than implying the switch only stops new tickets.
|
|
728
|
+
*
|
|
729
|
+
* Defaults to `true`: support being reachable is the safe state, and a
|
|
730
|
+
* settings document written before this field existed must not read as
|
|
731
|
+
* "support is off".
|
|
732
|
+
*/
|
|
733
|
+
support: {
|
|
734
|
+
enabled: boolean;
|
|
735
|
+
};
|
|
693
736
|
faq: {
|
|
694
737
|
variables: {
|
|
695
738
|
shippingDays: number;
|
|
@@ -808,6 +851,25 @@ export interface SiteSettingsDocument extends BaseDocument {
|
|
|
808
851
|
* opt-in and require the corresponding credentials to be set.
|
|
809
852
|
*/
|
|
810
853
|
notificationChannels?: NotificationChannelConfig;
|
|
854
|
+
/**
|
|
855
|
+
* The rate-change log behind `/admin/pricing`. Append-only, newest FIRST,
|
|
856
|
+
* capped at `RATE_CHANGE_LOG_MAX`.
|
|
857
|
+
*
|
|
858
|
+
* 🛑 **An array on the singleton rather than a collection, deliberately.**
|
|
859
|
+
* The page's only query is "the recent history of these 16 rates", which is
|
|
860
|
+
* one document read — and the rates themselves already live here, so a
|
|
861
|
+
* separate collection would mean two reads to render one table and two
|
|
862
|
+
* writes to record one change. It is capped for the same reason
|
|
863
|
+
* `statusHistory` is: an uncapped array on a hot singleton eventually makes
|
|
864
|
+
* every settings read expensive.
|
|
865
|
+
*
|
|
866
|
+
* 🛑 **Not an audit trail, and not a substitute for one.** A `pricing_update`
|
|
867
|
+
* row also goes to `adminAuditLog`, which is queryable and answers "what
|
|
868
|
+
* have admins done lately". This answers the narrower question the pricing
|
|
869
|
+
* page asks — "when did THIS rate last move, and to what" — and it is the
|
|
870
|
+
* one a truncation can safely lose.
|
|
871
|
+
*/
|
|
872
|
+
rateChanges?: RateChange[];
|
|
811
873
|
}
|
|
812
874
|
export declare const SITE_SETTINGS_COLLECTION: "siteSettings";
|
|
813
875
|
export declare const SITE_SETTINGS_INDEXED_FIELDS: readonly [];
|
|
@@ -377,6 +377,11 @@ export const DEFAULT_SITE_SETTINGS_DATA = {
|
|
|
377
377
|
returns: {
|
|
378
378
|
windowDays: 7,
|
|
379
379
|
},
|
|
380
|
+
// Reachable is the safe default, and an older settings document with no
|
|
381
|
+
// `support` group must not read as "support is off".
|
|
382
|
+
support: {
|
|
383
|
+
enabled: true,
|
|
384
|
+
},
|
|
380
385
|
announcementBar: {
|
|
381
386
|
enabled: true,
|
|
382
387
|
message: "🎉 Up to 15% Off on Pokémon TCG this week — Use code SAVE15",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The write contract for a self-serve ad booking.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 The shape cannot express moderation, payment or price
|
|
5
|
+
*
|
|
6
|
+
* This is Root Cause #76's rule applied to a surface where the submitter is
|
|
7
|
+
* a member of the public rather than an admin, which makes it sharper: an
|
|
8
|
+
* advertiser who can send `moderation: { state: "approved" }` has not
|
|
9
|
+
* bypassed a check, they have *become* the check. A schema that merely
|
|
10
|
+
* VALIDATED the field would still let `"approved"` through — the field has
|
|
11
|
+
* to be unrepresentable, so `.strict()` turns it into a 400 instead of
|
|
12
|
+
* something the server has to remember to overwrite.
|
|
13
|
+
*
|
|
14
|
+
* Same for `priceRs` (the server reads the rate card; a client-supplied
|
|
15
|
+
* price is a ₹1 banner) and `paymentState` (a booking that declares itself
|
|
16
|
+
* paid is a free slot).
|
|
17
|
+
*
|
|
18
|
+
* `placementId` and `period` ARE accepted: they are what is being bought,
|
|
19
|
+
* and they are also the booking's identity, so the conflict they can cause
|
|
20
|
+
* is a document collision rather than a validation question.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
/**
|
|
24
|
+
* 🛑 Creative fields are bounded, and `ctaHref` is http(s)-only.
|
|
25
|
+
*
|
|
26
|
+
* An unbounded `body` is a storage cost per booking and a layout break on
|
|
27
|
+
* every page carrying the slot. A `javascript:` or `data:` CTA is script
|
|
28
|
+
* execution on every page the creative renders on, submitted by a member of
|
|
29
|
+
* the public — this is the one field on this schema where a miss is a
|
|
30
|
+
* security defect rather than a tidiness one.
|
|
31
|
+
*/
|
|
32
|
+
export declare const httpUrl: z.ZodEffects<z.ZodString, string, string>;
|
|
33
|
+
export declare const adBookingCreativeSchema: z.ZodObject<{
|
|
34
|
+
title: z.ZodString;
|
|
35
|
+
body: z.ZodOptional<z.ZodString>;
|
|
36
|
+
imageUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
37
|
+
ctaLabel: z.ZodOptional<z.ZodString>;
|
|
38
|
+
ctaHref: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
39
|
+
}, "strict", z.ZodTypeAny, {
|
|
40
|
+
title: string;
|
|
41
|
+
body?: string | undefined;
|
|
42
|
+
imageUrl?: string | undefined;
|
|
43
|
+
ctaLabel?: string | undefined;
|
|
44
|
+
ctaHref?: string | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
title: string;
|
|
47
|
+
body?: string | undefined;
|
|
48
|
+
imageUrl?: string | undefined;
|
|
49
|
+
ctaLabel?: string | undefined;
|
|
50
|
+
ctaHref?: string | undefined;
|
|
51
|
+
}>;
|
|
52
|
+
export declare const adBookingWriteSchema: z.ZodObject<{
|
|
53
|
+
placementId: z.ZodString;
|
|
54
|
+
period: z.ZodEffects<z.ZodString, string, string>;
|
|
55
|
+
creative: z.ZodObject<{
|
|
56
|
+
title: z.ZodString;
|
|
57
|
+
body: z.ZodOptional<z.ZodString>;
|
|
58
|
+
imageUrl: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
59
|
+
ctaLabel: z.ZodOptional<z.ZodString>;
|
|
60
|
+
ctaHref: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
61
|
+
}, "strict", z.ZodTypeAny, {
|
|
62
|
+
title: string;
|
|
63
|
+
body?: string | undefined;
|
|
64
|
+
imageUrl?: string | undefined;
|
|
65
|
+
ctaLabel?: string | undefined;
|
|
66
|
+
ctaHref?: string | undefined;
|
|
67
|
+
}, {
|
|
68
|
+
title: string;
|
|
69
|
+
body?: string | undefined;
|
|
70
|
+
imageUrl?: string | undefined;
|
|
71
|
+
ctaLabel?: string | undefined;
|
|
72
|
+
ctaHref?: string | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
}, "strict", z.ZodTypeAny, {
|
|
75
|
+
placementId: string;
|
|
76
|
+
period: string;
|
|
77
|
+
creative: {
|
|
78
|
+
title: string;
|
|
79
|
+
body?: string | undefined;
|
|
80
|
+
imageUrl?: string | undefined;
|
|
81
|
+
ctaLabel?: string | undefined;
|
|
82
|
+
ctaHref?: string | undefined;
|
|
83
|
+
};
|
|
84
|
+
}, {
|
|
85
|
+
placementId: string;
|
|
86
|
+
period: string;
|
|
87
|
+
creative: {
|
|
88
|
+
title: string;
|
|
89
|
+
body?: string | undefined;
|
|
90
|
+
imageUrl?: string | undefined;
|
|
91
|
+
ctaLabel?: string | undefined;
|
|
92
|
+
ctaHref?: string | undefined;
|
|
93
|
+
};
|
|
94
|
+
}>;
|
|
95
|
+
export type AdBookingWriteInput = z.infer<typeof adBookingWriteSchema>;
|
|
96
|
+
/**
|
|
97
|
+
* A moderator's verdict.
|
|
98
|
+
*
|
|
99
|
+
* 🛑 A rejection REQUIRES a note, for the same reason an admin offer-cancel
|
|
100
|
+
* does: without one the advertiser's next submission is the same creative
|
|
101
|
+
* again, and the moderator reviews it twice. An approval takes no note
|
|
102
|
+
* because there is nothing to say.
|
|
103
|
+
*/
|
|
104
|
+
export declare const adModerationSchema: z.ZodEffects<z.ZodObject<{
|
|
105
|
+
approve: z.ZodBoolean;
|
|
106
|
+
note: z.ZodOptional<z.ZodString>;
|
|
107
|
+
}, "strict", z.ZodTypeAny, {
|
|
108
|
+
approve: boolean;
|
|
109
|
+
note?: string | undefined;
|
|
110
|
+
}, {
|
|
111
|
+
approve: boolean;
|
|
112
|
+
note?: string | undefined;
|
|
113
|
+
}>, {
|
|
114
|
+
approve: boolean;
|
|
115
|
+
note?: string | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
approve: boolean;
|
|
118
|
+
note?: string | undefined;
|
|
119
|
+
}>;
|
|
120
|
+
export type AdModerationInput = z.infer<typeof adModerationSchema>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The write contract for a self-serve ad booking.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 The shape cannot express moderation, payment or price
|
|
5
|
+
*
|
|
6
|
+
* This is Root Cause #76's rule applied to a surface where the submitter is
|
|
7
|
+
* a member of the public rather than an admin, which makes it sharper: an
|
|
8
|
+
* advertiser who can send `moderation: { state: "approved" }` has not
|
|
9
|
+
* bypassed a check, they have *become* the check. A schema that merely
|
|
10
|
+
* VALIDATED the field would still let `"approved"` through — the field has
|
|
11
|
+
* to be unrepresentable, so `.strict()` turns it into a 400 instead of
|
|
12
|
+
* something the server has to remember to overwrite.
|
|
13
|
+
*
|
|
14
|
+
* Same for `priceRs` (the server reads the rate card; a client-supplied
|
|
15
|
+
* price is a ₹1 banner) and `paymentState` (a booking that declares itself
|
|
16
|
+
* paid is a free slot).
|
|
17
|
+
*
|
|
18
|
+
* `placementId` and `period` ARE accepted: they are what is being bought,
|
|
19
|
+
* and they are also the booking's identity, so the conflict they can cause
|
|
20
|
+
* is a document collision rather than a validation question.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
import { isAdPeriod } from "./firestore.js";
|
|
24
|
+
/**
|
|
25
|
+
* 🛑 Creative fields are bounded, and `ctaHref` is http(s)-only.
|
|
26
|
+
*
|
|
27
|
+
* An unbounded `body` is a storage cost per booking and a layout break on
|
|
28
|
+
* every page carrying the slot. A `javascript:` or `data:` CTA is script
|
|
29
|
+
* execution on every page the creative renders on, submitted by a member of
|
|
30
|
+
* the public — this is the one field on this schema where a miss is a
|
|
31
|
+
* security defect rather than a tidiness one.
|
|
32
|
+
*/
|
|
33
|
+
/*
|
|
34
|
+
* Exported so `creative-form.ts` reuses the REFINEMENT rather than restating
|
|
35
|
+
* it — the form and the wire must agree on what a link is, and a second copy
|
|
36
|
+
* of a security check is a second thing to forget.
|
|
37
|
+
*/
|
|
38
|
+
export const httpUrl = z
|
|
39
|
+
.string()
|
|
40
|
+
.url()
|
|
41
|
+
.refine((u) => /^https?:\/\//i.test(u), "Links must start with http:// or https://");
|
|
42
|
+
export const adBookingCreativeSchema = z
|
|
43
|
+
.object({
|
|
44
|
+
title: z.string().min(2).max(80),
|
|
45
|
+
body: z.string().max(200).optional(),
|
|
46
|
+
imageUrl: httpUrl.optional(),
|
|
47
|
+
ctaLabel: z.string().max(40).optional(),
|
|
48
|
+
ctaHref: httpUrl.optional(),
|
|
49
|
+
})
|
|
50
|
+
.strict();
|
|
51
|
+
export const adBookingWriteSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
placementId: z.string().min(1).max(80),
|
|
54
|
+
period: z.string().refine(isAdPeriod, "Pick a month, as YYYY-MM."),
|
|
55
|
+
creative: adBookingCreativeSchema,
|
|
56
|
+
})
|
|
57
|
+
.strict();
|
|
58
|
+
/**
|
|
59
|
+
* A moderator's verdict.
|
|
60
|
+
*
|
|
61
|
+
* 🛑 A rejection REQUIRES a note, for the same reason an admin offer-cancel
|
|
62
|
+
* does: without one the advertiser's next submission is the same creative
|
|
63
|
+
* again, and the moderator reviews it twice. An approval takes no note
|
|
64
|
+
* because there is nothing to say.
|
|
65
|
+
*/
|
|
66
|
+
export const adModerationSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
approve: z.boolean(),
|
|
69
|
+
note: z.string().max(300).optional(),
|
|
70
|
+
})
|
|
71
|
+
.strict()
|
|
72
|
+
.refine((v) => v.approve || (v.note?.trim().length ?? 0) >= 10, {
|
|
73
|
+
message: "Say why it was rejected — the advertiser sees this and will resubmit without it.",
|
|
74
|
+
path: ["note"],
|
|
75
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const adCreativeFormSchema: z.ZodObject<{
|
|
3
|
+
title: z.ZodString;
|
|
4
|
+
body: z.ZodOptional<z.ZodString>;
|
|
5
|
+
ctaLabel: z.ZodOptional<z.ZodString>;
|
|
6
|
+
ctaHref: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"">, z.ZodEffects<z.ZodString, string, string>]>>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
title: string;
|
|
9
|
+
body?: string | undefined;
|
|
10
|
+
ctaLabel?: string | undefined;
|
|
11
|
+
ctaHref?: string | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
title: string;
|
|
14
|
+
body?: string | undefined;
|
|
15
|
+
ctaLabel?: string | undefined;
|
|
16
|
+
ctaHref?: string | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type AdCreativeFormValues = z.infer<typeof adCreativeFormSchema>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: `/advertise` rendered four hand-wired `<FieldInput>`s inside a bare
|
|
3
|
+
* `<Form>`, so the advertiser's creative had no client-side bounds at
|
|
4
|
+
* all — the only limits were the ones `adBookingCreateSchema` enforces
|
|
5
|
+
* server-side, which the visitor meets as a 400 after submitting. A
|
|
6
|
+
* headline is the single most visible string this platform renders to
|
|
7
|
+
* strangers; it should not be the one field with no feedback until POST.
|
|
8
|
+
*
|
|
9
|
+
* WHAT: The FLAT form shape for the booking creative, annotated so
|
|
10
|
+
* `buildSectionsFromSchema` produces the fields. The wire shape nests
|
|
11
|
+
* these under `creative` (see `booking-write.ts`); the page lifts them
|
|
12
|
+
* at submit.
|
|
13
|
+
*
|
|
14
|
+
* 🛑 It deliberately does NOT carry `placementId` or `period`. Those are
|
|
15
|
+
* chosen by clicking a month in the rate card, not typed — and more to the
|
|
16
|
+
* point, a slot whose availability the server has already decided must not
|
|
17
|
+
* become a text input the advertiser can edit. The booking id IS the lock
|
|
18
|
+
* (`adBookingId`), so a typed period is a way to aim at somebody else's slot.
|
|
19
|
+
*
|
|
20
|
+
* 🛑 Bounds mirror `adCreativeSchema` exactly. Two numbers that merely happen
|
|
21
|
+
* to agree today would drift into a form that accepts what the route refuses,
|
|
22
|
+
* which is the worse of the two failures: it looks like a server fault.
|
|
23
|
+
*
|
|
24
|
+
* EXPORTS: adCreativeFormSchema, type AdCreativeFormValues
|
|
25
|
+
*
|
|
26
|
+
* @tag domain:ads
|
|
27
|
+
* @tag layer:schema
|
|
28
|
+
* @tag pattern:none
|
|
29
|
+
* @tag access:isomorphic
|
|
30
|
+
* @tag consumers:/advertise
|
|
31
|
+
* @tag sideEffects:none
|
|
32
|
+
*/
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
import { annotate } from "../../shell/field-ui-meta.js";
|
|
35
|
+
import { httpUrl } from "./booking-write.js";
|
|
36
|
+
export const adCreativeFormSchema = z.object({
|
|
37
|
+
title: annotate(z.string().trim().min(2, "A headline is required.").max(80, "Keep the headline under 80 characters."), { section: "creative", sectionLabel: "Your creative", sectionRequired: true, quick: true, order: 1, row: "full" }),
|
|
38
|
+
body: annotate(z.string().trim().max(200, "Keep the body under 200 characters.").optional(), { section: "creative", order: 2, row: "full", kind: "textarea" }),
|
|
39
|
+
ctaLabel: annotate(z.string().trim().max(40, "Keep the button text under 40 characters.").optional(), { section: "creative", order: 3, row: "pair" }),
|
|
40
|
+
/*
|
|
41
|
+
* 🛑 `httpUrl`, the same refinement the wire schema uses — a `javascript:`
|
|
42
|
+
* or `data:` CTA on a page we render to strangers is stored XSS with our
|
|
43
|
+
* own domain's credibility behind it. An empty string is allowed through so
|
|
44
|
+
* clearing the field is not an error; the page drops it before POST.
|
|
45
|
+
*/
|
|
46
|
+
ctaHref: annotate(z.union([z.literal(""), httpUrl]).optional(), {
|
|
47
|
+
section: "creative",
|
|
48
|
+
order: 4,
|
|
49
|
+
row: "pair",
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D56 — a SELF-SERVE ad booking: one advertiser, one placement, one period.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 Flat fee per slot per period, and explicitly NOT CPM
|
|
5
|
+
*
|
|
6
|
+
* Impression counting is a write per page view, which is the exact cost
|
|
7
|
+
* pattern that suspended this project (Root Cause #104: 3.1M ISR writes
|
|
8
|
+
* against a 200K allowance, 52.52 GB of Fast Origin Transfer against 10 GB,
|
|
9
|
+
* for eleven monthly active users). A flat fee is one write per BOOKING.
|
|
10
|
+
* Nothing here counts anything per render, and nothing should be added that
|
|
11
|
+
* does.
|
|
12
|
+
*
|
|
13
|
+
* ## Why a PERIOD rather than an arbitrary date range
|
|
14
|
+
*
|
|
15
|
+
* The plan's requirement is slot-availability locking — two advertisers must
|
|
16
|
+
* not book the same slot for overlapping dates. Firestore has no range
|
|
17
|
+
* constraint, so an arbitrary `startAt`/`endAt` pair can only be checked by
|
|
18
|
+
* QUERYING for overlaps and then writing, and two concurrent bookings both
|
|
19
|
+
* read "no overlap" and both write. That race is invisible in testing and
|
|
20
|
+
* sells the same slot twice.
|
|
21
|
+
*
|
|
22
|
+
* Discretising to a period makes the conflict a DOCUMENT COLLISION instead:
|
|
23
|
+
* the booking id is derived from `(placementId, period)`, so the second
|
|
24
|
+
* writer fails on an existing document inside its own transaction and
|
|
25
|
+
* Firestore does the locking. There is no query to race against.
|
|
26
|
+
*
|
|
27
|
+
* It also matches what is being sold. "The homepage banner for November" is
|
|
28
|
+
* the product; "the homepage banner from the 9th to the 23rd" is a pricing
|
|
29
|
+
* model nobody asked for and an availability calendar nobody can render.
|
|
30
|
+
*/
|
|
31
|
+
import type { BaseDocument } from "../../../_internal/shared/types/base-document";
|
|
32
|
+
export declare const AD_BOOKING_COLLECTION = "adBookings";
|
|
33
|
+
/**
|
|
34
|
+
* A calendar month, `YYYY-MM`.
|
|
35
|
+
*
|
|
36
|
+
* 🛑 A STRING, not a Date. It is an identity — half of the booking's primary
|
|
37
|
+
* key — and a Date would make "the same month" a comparison rather than an
|
|
38
|
+
* equality, which is precisely what the document-collision lock depends on
|
|
39
|
+
* not being.
|
|
40
|
+
*/
|
|
41
|
+
export type AdPeriod = string;
|
|
42
|
+
export declare function isAdPeriod(value: string): value is AdPeriod;
|
|
43
|
+
/** The period a date falls in, in UTC. */
|
|
44
|
+
export declare function adPeriodOf(date: Date): AdPeriod;
|
|
45
|
+
/** First instant of a period, UTC. */
|
|
46
|
+
export declare function adPeriodStart(period: AdPeriod): Date;
|
|
47
|
+
/** First instant of the NEXT period — the exclusive end. */
|
|
48
|
+
export declare function adPeriodEnd(period: AdPeriod): Date;
|
|
49
|
+
/**
|
|
50
|
+
* 🛑 The booking id IS the lock. Derived, never generated.
|
|
51
|
+
*
|
|
52
|
+
* Two advertisers booking `banner-home` for `2026-11` compute the same id and
|
|
53
|
+
* the second `tx.create` throws `ALREADY_EXISTS` — which is the whole
|
|
54
|
+
* availability guarantee, enforced by Firestore rather than by a check
|
|
55
|
+
* somebody could forget to run.
|
|
56
|
+
*/
|
|
57
|
+
export declare function adBookingId(placementId: string, period: AdPeriod): string;
|
|
58
|
+
/**
|
|
59
|
+
* Payment state. Deliberately coarse: this records whether the slot is PAID
|
|
60
|
+
* FOR, not how. The invoice and the ledger posting are Part 4's job and carry
|
|
61
|
+
* the detail; duplicating any of it here would be two records of one fact.
|
|
62
|
+
*/
|
|
63
|
+
export declare const AD_BOOKING_PAYMENT_STATES: readonly ["unpaid", "paid", "refunded"];
|
|
64
|
+
export type AdBookingPaymentState = (typeof AD_BOOKING_PAYMENT_STATES)[number];
|
|
65
|
+
/**
|
|
66
|
+
* Creative moderation. **Nothing renders on the site until `approved`.**
|
|
67
|
+
*
|
|
68
|
+
* 🛑 `pending` is the initial value and there is no way to write `approved`
|
|
69
|
+
* through the advertiser's own schema — see `adBookingWriteSchema`. A
|
|
70
|
+
* self-serve flow where the submitter can set their own moderation state is
|
|
71
|
+
* not moderated; it is a form with an extra field (Root Cause #76 — a field
|
|
72
|
+
* the form can send is a field the form can destroy, here inverted into a
|
|
73
|
+
* field the form can grant itself).
|
|
74
|
+
*/
|
|
75
|
+
export declare const AD_MODERATION_STATES: readonly ["pending", "approved", "rejected"];
|
|
76
|
+
export type AdModerationState = (typeof AD_MODERATION_STATES)[number];
|
|
77
|
+
export interface AdBookingCreative {
|
|
78
|
+
title: string;
|
|
79
|
+
body?: string;
|
|
80
|
+
imageUrl?: string;
|
|
81
|
+
ctaLabel?: string;
|
|
82
|
+
ctaHref?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface AdBookingDocument extends BaseDocument {
|
|
85
|
+
/** Matches a `SiteSettingsAdPlacement.id`. */
|
|
86
|
+
placementId: string;
|
|
87
|
+
period: AdPeriod;
|
|
88
|
+
/** Auth uid of the advertiser. */
|
|
89
|
+
advertiserUid: string;
|
|
90
|
+
/** Denormalised for the admin queue — a moderator should not fan out to `users`. */
|
|
91
|
+
advertiserName?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Rupees, SNAPSHOTTED at booking.
|
|
94
|
+
*
|
|
95
|
+
* 🛑 Never recomputed from the live rate card. The rate is a price the
|
|
96
|
+
* advertiser agreed to; re-deriving it at render or invoice time would
|
|
97
|
+
* silently reprice a sold slot the first time an admin edits the card —
|
|
98
|
+
* the same rule `sourceContext` follows for order provenance.
|
|
99
|
+
*/
|
|
100
|
+
priceRs: number;
|
|
101
|
+
paymentState: AdBookingPaymentState;
|
|
102
|
+
/** Set by the Part 4 invoicing path once the booking is billed. */
|
|
103
|
+
invoiceId?: string;
|
|
104
|
+
creative: AdBookingCreative;
|
|
105
|
+
moderation: {
|
|
106
|
+
state: AdModerationState;
|
|
107
|
+
/** Required on a rejection — see `moderateAdCreative`. */
|
|
108
|
+
note?: string;
|
|
109
|
+
reviewedAt?: Date;
|
|
110
|
+
/**
|
|
111
|
+
* Staff uid. 🛑 Never returned to the advertiser: who rejected you is
|
|
112
|
+
* not information a self-serve submitter needs, and naming an individual
|
|
113
|
+
* moderator invites them being contacted directly.
|
|
114
|
+
*/
|
|
115
|
+
reviewedBy?: string;
|
|
116
|
+
};
|
|
117
|
+
/** Set when an admin or the advertiser cancels. A cancelled booking frees nothing — see below. */
|
|
118
|
+
cancelledAt?: Date;
|
|
119
|
+
cancelledReason?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Does this booking put a creative on the page right now?
|
|
123
|
+
*
|
|
124
|
+
* 🛑 All four conditions, and the order is not an accident — moderation is
|
|
125
|
+
* checked before the calendar so an approved-but-future booking and an
|
|
126
|
+
* unreviewed current one are distinguishable in a debugger.
|
|
127
|
+
*/
|
|
128
|
+
export declare function isAdBookingLive(booking: Pick<AdBookingDocument, "moderation" | "paymentState" | "period" | "cancelledAt">, now?: Date): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* 🛑 A cancelled booking KEEPS its document, and therefore keeps the slot
|
|
131
|
+
* locked for its own period.
|
|
132
|
+
*
|
|
133
|
+
* Deleting it would free the slot — which sounds like the point and is the
|
|
134
|
+
* wrong behaviour twice over: the advertiser has paid for a period that has
|
|
135
|
+
* possibly already started, and re-selling a month mid-flight means two
|
|
136
|
+
* creatives were live in one slot at different times with one invoice
|
|
137
|
+
* between them. Freeing a period is an ADMIN act (`releaseAdSlot`), done
|
|
138
|
+
* knowingly, not a side effect of a cancel button.
|
|
139
|
+
*/
|
|
140
|
+
export declare const AD_BOOKING_CANCELLED_KEEPS_SLOT = true;
|