@aglyn/plugins-commerce 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +10 -0
- package/package.json +57 -0
- package/src/index.d.ts +38 -0
- package/src/index.js +38 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/account.d.ts +31 -0
- package/src/lib/components/account.js +645 -0
- package/src/lib/components/account.js.map +1 -0
- package/src/lib/components/cart.d.ts +38 -0
- package/src/lib/components/cart.js +851 -0
- package/src/lib/components/cart.js.map +1 -0
- package/src/lib/components/commerce-console-page.d.ts +32 -0
- package/src/lib/components/commerce-console-page.js +296 -0
- package/src/lib/components/commerce-console-page.js.map +1 -0
- package/src/lib/components/commerce-console-sections.d.ts +34 -0
- package/src/lib/components/commerce-console-sections.js +62 -0
- package/src/lib/components/commerce-console-sections.js.map +1 -0
- package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
- package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
- package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
- package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
- package/src/lib/components/console/commerce-glance-card.component.js +340 -0
- package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
- package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
- package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
- package/src/lib/components/console/discounts-card.component.d.ts +14 -0
- package/src/lib/components/console/discounts-card.component.js +443 -0
- package/src/lib/components/console/discounts-card.component.js.map +1 -0
- package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
- package/src/lib/components/console/entitlement-gate.component.js +115 -0
- package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
- package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
- package/src/lib/components/console/gift-cards-card.component.js +379 -0
- package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
- package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
- package/src/lib/components/console/host-coupons-card.component.js +252 -0
- package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
- package/src/lib/components/console/host-orders-card.component.js +861 -0
- package/src/lib/components/console/host-orders-card.component.js.map +1 -0
- package/src/lib/components/console/locations-card.component.d.ts +14 -0
- package/src/lib/components/console/locations-card.component.js +256 -0
- package/src/lib/components/console/locations-card.component.js.map +1 -0
- package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
- package/src/lib/components/console/member-posts-card.component.js +283 -0
- package/src/lib/components/console/member-posts-card.component.js.map +1 -0
- package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
- package/src/lib/components/console/newest-site-users-card.component.js +126 -0
- package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
- package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
- package/src/lib/components/console/order-detail-dialog.component.js +976 -0
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
- package/src/lib/components/console/paid-media.d.ts +127 -0
- package/src/lib/components/console/paid-media.js +397 -0
- package/src/lib/components/console/paid-media.js.map +1 -0
- package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
- package/src/lib/components/console/payments-settings-card.component.js +295 -0
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
- package/src/lib/components/console/pos-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-page.component.js +916 -0
- package/src/lib/components/console/pos-page.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
- package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
- package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
- package/src/lib/components/console/products-hub-card.component.js +1280 -0
- package/src/lib/components/console/products-hub-card.component.js.map +1 -0
- package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
- package/src/lib/components/console/products-hub-zone.component.js +200 -0
- package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
- package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
- package/src/lib/components/console/recovery-queue-card.component.js +262 -0
- package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
- package/src/lib/components/console/registers-card.component.d.ts +21 -0
- package/src/lib/components/console/registers-card.component.js +296 -0
- package/src/lib/components/console/registers-card.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +14 -0
- package/src/lib/components/console/reservations-card.component.js +650 -0
- package/src/lib/components/console/reservations-card.component.js.map +1 -0
- package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
- package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
- package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
- package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
- package/src/lib/components/console/shipping-settings-card.component.js +560 -0
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
- package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
- package/src/lib/components/console/stock-movements-card.component.js +333 -0
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
- package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/store-settings-card.component.js +300 -0
- package/src/lib/components/console/store-settings-card.component.js.map +1 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
- package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
- package/src/lib/components/console/suppliers-card.component.js +328 -0
- package/src/lib/components/console/suppliers-card.component.js.map +1 -0
- package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/tax-settings-card.component.js +473 -0
- package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
- package/src/lib/components/gate.d.ts +39 -0
- package/src/lib/components/gate.js +202 -0
- package/src/lib/components/gate.js.map +1 -0
- package/src/lib/components/gated-video.d.ts +40 -0
- package/src/lib/components/gated-video.js +366 -0
- package/src/lib/components/gated-video.js.map +1 -0
- package/src/lib/components/member-feed.d.ts +32 -0
- package/src/lib/components/member-feed.js +198 -0
- package/src/lib/components/member-feed.js.map +1 -0
- package/src/lib/components/member-recovery.d.ts +35 -0
- package/src/lib/components/member-recovery.js +313 -0
- package/src/lib/components/member-recovery.js.map +1 -0
- package/src/lib/components/member-signin.d.ts +35 -0
- package/src/lib/components/member-signin.js +257 -0
- package/src/lib/components/member-signin.js.map +1 -0
- package/src/lib/components/member-signup.d.ts +34 -0
- package/src/lib/components/member-signup.js +287 -0
- package/src/lib/components/member-signup.js.map +1 -0
- package/src/lib/components/newsletter-signup.d.ts +39 -0
- package/src/lib/components/newsletter-signup.js +229 -0
- package/src/lib/components/newsletter-signup.js.map +1 -0
- package/src/lib/components/product-detail.d.ts +38 -0
- package/src/lib/components/product-detail.js +1022 -0
- package/src/lib/components/product-detail.js.map +1 -0
- package/src/lib/components/product-grid.d.ts +67 -0
- package/src/lib/components/product-grid.js +909 -0
- package/src/lib/components/product-grid.js.map +1 -0
- package/src/lib/components/product-reviews.d.ts +32 -0
- package/src/lib/components/product-reviews.js +349 -0
- package/src/lib/components/product-reviews.js.map +1 -0
- package/src/lib/components/related-products.d.ts +33 -0
- package/src/lib/components/related-products.js +232 -0
- package/src/lib/components/related-products.js.map +1 -0
- package/src/lib/components/reservation-widget.d.ts +33 -0
- package/src/lib/components/reservation-widget.js +418 -0
- package/src/lib/components/reservation-widget.js.map +1 -0
- package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
- package/src/lib/components/storefront-payment-element-fallback.js +51 -0
- package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +78 -0
- package/src/lib/components/storefront-payment-element.js +156 -0
- package/src/lib/components/storefront-payment-element.js.map +1 -0
- package/src/lib/components/wishlist.d.ts +46 -0
- package/src/lib/components/wishlist.js +304 -0
- package/src/lib/components/wishlist.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +18 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/product-filters.d.ts +35 -0
- package/src/lib/constants/product-filters.js +109 -0
- package/src/lib/constants/product-filters.js.map +1 -0
- package/src/lib/model/commerce-cart.d.ts +52 -0
- package/src/lib/model/commerce-cart.js +102 -0
- package/src/lib/model/commerce-cart.js.map +1 -0
- package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
- package/src/lib/model/commerce-connect-transfer.js +231 -0
- package/src/lib/model/commerce-connect-transfer.js.map +1 -0
- package/src/lib/model/commerce-discounts.d.ts +164 -0
- package/src/lib/model/commerce-discounts.js +231 -0
- package/src/lib/model/commerce-discounts.js.map +1 -0
- package/src/lib/model/commerce-dispute.d.ts +124 -0
- package/src/lib/model/commerce-dispute.js +225 -0
- package/src/lib/model/commerce-dispute.js.map +1 -0
- package/src/lib/model/commerce-gift-cards.d.ts +107 -0
- package/src/lib/model/commerce-gift-cards.js +121 -0
- package/src/lib/model/commerce-gift-cards.js.map +1 -0
- package/src/lib/model/commerce-io.d.ts +36 -0
- package/src/lib/model/commerce-io.js +245 -0
- package/src/lib/model/commerce-io.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +1040 -0
- package/src/lib/model/commerce-orders.js +1022 -0
- package/src/lib/model/commerce-orders.js.map +1 -0
- package/src/lib/model/commerce-promotions.d.ts +188 -0
- package/src/lib/model/commerce-promotions.js +199 -0
- package/src/lib/model/commerce-promotions.js.map +1 -0
- package/src/lib/model/commerce-reservations.d.ts +175 -0
- package/src/lib/model/commerce-reservations.js +157 -0
- package/src/lib/model/commerce-reservations.js.map +1 -0
- package/src/lib/model/commerce-shipping.d.ts +316 -0
- package/src/lib/model/commerce-shipping.js +484 -0
- package/src/lib/model/commerce-shipping.js.map +1 -0
- package/src/lib/model/commerce-stock-holds.d.ts +199 -0
- package/src/lib/model/commerce-stock-holds.js +190 -0
- package/src/lib/model/commerce-stock-holds.js.map +1 -0
- package/src/lib/model/commerce-subscription-status.d.ts +67 -0
- package/src/lib/model/commerce-subscription-status.js +76 -0
- package/src/lib/model/commerce-subscription-status.js.map +1 -0
- package/src/lib/model/commerce-tax-decision.d.ts +222 -0
- package/src/lib/model/commerce-tax-decision.js +165 -0
- package/src/lib/model/commerce-tax-decision.js.map +1 -0
- package/src/lib/model/commerce-tax.d.ts +176 -0
- package/src/lib/model/commerce-tax.js +92 -0
- package/src/lib/model/commerce-tax.js.map +1 -0
- package/src/lib/model/commerce.d.ts +551 -0
- package/src/lib/model/commerce.js +739 -0
- package/src/lib/model/commerce.js.map +1 -0
- package/src/lib/model/index.d.ts +40 -0
- package/src/lib/model/index.js +40 -0
- package/src/lib/model/index.js.map +1 -0
- package/src/lib/model/order-figures.d.ts +48 -0
- package/src/lib/model/order-figures.js +74 -0
- package/src/lib/model/order-figures.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +23 -0
- package/src/lib/model/plugin-permissions.js +34 -0
- package/src/lib/model/plugin-permissions.js.map +1 -0
- package/src/lib/model/purchase-analytics.d.ts +186 -0
- package/src/lib/model/purchase-analytics.js +216 -0
- package/src/lib/model/purchase-analytics.js.map +1 -0
- package/src/lib/plugin-config.d.ts +62 -0
- package/src/lib/plugin-config.js +78 -0
- package/src/lib/plugin-config.js.map +1 -0
- package/src/lib/plugin.d.ts +28 -0
- package/src/lib/plugin.js +147 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/billing-webhook.d.ts +26 -0
- package/src/lib/server/billing-webhook.js +4011 -0
- package/src/lib/server/billing-webhook.js.map +1 -0
- package/src/lib/server/cancel-order.d.ts +87 -0
- package/src/lib/server/cancel-order.js +368 -0
- package/src/lib/server/cancel-order.js.map +1 -0
- package/src/lib/server/cart-checkout.d.ts +25 -0
- package/src/lib/server/cart-checkout.js +976 -0
- package/src/lib/server/cart-checkout.js.map +1 -0
- package/src/lib/server/cart-cookie.d.ts +32 -0
- package/src/lib/server/cart-cookie.js +77 -0
- package/src/lib/server/cart-cookie.js.map +1 -0
- package/src/lib/server/cart.d.ts +34 -0
- package/src/lib/server/cart.js +181 -0
- package/src/lib/server/cart.js.map +1 -0
- package/src/lib/server/catalog.d.ts +127 -0
- package/src/lib/server/catalog.js +277 -0
- package/src/lib/server/catalog.js.map +1 -0
- package/src/lib/server/checkout.d.ts +36 -0
- package/src/lib/server/checkout.js +915 -0
- package/src/lib/server/checkout.js.map +1 -0
- package/src/lib/server/connect.d.ts +26 -0
- package/src/lib/server/connect.js +238 -0
- package/src/lib/server/connect.js.map +1 -0
- package/src/lib/server/contact-refund.d.ts +117 -0
- package/src/lib/server/contact-refund.js +196 -0
- package/src/lib/server/contact-refund.js.map +1 -0
- package/src/lib/server/download.d.ts +39 -0
- package/src/lib/server/download.js +206 -0
- package/src/lib/server/download.js.map +1 -0
- package/src/lib/server/draft-order.d.ts +26 -0
- package/src/lib/server/draft-order.js +706 -0
- package/src/lib/server/draft-order.js.map +1 -0
- package/src/lib/server/feed.d.ts +24 -0
- package/src/lib/server/feed.js +59 -0
- package/src/lib/server/feed.js.map +1 -0
- package/src/lib/server/fulfill-order.d.ts +97 -0
- package/src/lib/server/fulfill-order.js +235 -0
- package/src/lib/server/fulfill-order.js.map +1 -0
- package/src/lib/server/gate.d.ts +36 -0
- package/src/lib/server/gate.js +112 -0
- package/src/lib/server/gate.js.map +1 -0
- package/src/lib/server/gift-cards.d.ts +42 -0
- package/src/lib/server/gift-cards.js +219 -0
- package/src/lib/server/gift-cards.js.map +1 -0
- package/src/lib/server/low-stock.d.ts +49 -0
- package/src/lib/server/low-stock.js +60 -0
- package/src/lib/server/low-stock.js.map +1 -0
- package/src/lib/server/manual-tax-rate.d.ts +82 -0
- package/src/lib/server/manual-tax-rate.js +113 -0
- package/src/lib/server/manual-tax-rate.js.map +1 -0
- package/src/lib/server/member-feed.d.ts +24 -0
- package/src/lib/server/member-feed.js +72 -0
- package/src/lib/server/member-feed.js.map +1 -0
- package/src/lib/server/member-name-search.d.ts +37 -0
- package/src/lib/server/member-name-search.js +42 -0
- package/src/lib/server/member-name-search.js.map +1 -0
- package/src/lib/server/member-post.d.ts +23 -0
- package/src/lib/server/member-post.js +166 -0
- package/src/lib/server/member-post.js.map +1 -0
- package/src/lib/server/membership-account.d.ts +37 -0
- package/src/lib/server/membership-account.js +148 -0
- package/src/lib/server/membership-account.js.map +1 -0
- package/src/lib/server/membership-admin-password.d.ts +33 -0
- package/src/lib/server/membership-admin-password.js +202 -0
- package/src/lib/server/membership-admin-password.js.map +1 -0
- package/src/lib/server/membership-content.d.ts +23 -0
- package/src/lib/server/membership-content.js +105 -0
- package/src/lib/server/membership-content.js.map +1 -0
- package/src/lib/server/membership-login.d.ts +19 -0
- package/src/lib/server/membership-login.js +137 -0
- package/src/lib/server/membership-login.js.map +1 -0
- package/src/lib/server/membership-logout.d.ts +19 -0
- package/src/lib/server/membership-logout.js +35 -0
- package/src/lib/server/membership-logout.js.map +1 -0
- package/src/lib/server/membership-recover.d.ts +60 -0
- package/src/lib/server/membership-recover.js +244 -0
- package/src/lib/server/membership-recover.js.map +1 -0
- package/src/lib/server/membership-register.d.ts +22 -0
- package/src/lib/server/membership-register.js +241 -0
- package/src/lib/server/membership-register.js.map +1 -0
- package/src/lib/server/membership-reset.d.ts +26 -0
- package/src/lib/server/membership-reset.js +88 -0
- package/src/lib/server/membership-reset.js.map +1 -0
- package/src/lib/server/membership-wishlist.d.ts +23 -0
- package/src/lib/server/membership-wishlist.js +89 -0
- package/src/lib/server/membership-wishlist.js.map +1 -0
- package/src/lib/server/membership.d.ts +96 -0
- package/src/lib/server/membership.js +222 -0
- package/src/lib/server/membership.js.map +1 -0
- package/src/lib/server/native-checkout.d.ts +170 -0
- package/src/lib/server/native-checkout.js +193 -0
- package/src/lib/server/native-checkout.js.map +1 -0
- package/src/lib/server/newsletter.d.ts +23 -0
- package/src/lib/server/newsletter.js +323 -0
- package/src/lib/server/newsletter.js.map +1 -0
- package/src/lib/server/notify-restock.d.ts +22 -0
- package/src/lib/server/notify-restock.js +84 -0
- package/src/lib/server/notify-restock.js.map +1 -0
- package/src/lib/server/order-analytics.d.ts +134 -0
- package/src/lib/server/order-analytics.js +263 -0
- package/src/lib/server/order-analytics.js.map +1 -0
- package/src/lib/server/order-figures.d.ts +33 -0
- package/src/lib/server/order-figures.js +220 -0
- package/src/lib/server/order-figures.js.map +1 -0
- package/src/lib/server/paid-media-delivery.d.ts +173 -0
- package/src/lib/server/paid-media-delivery.js +212 -0
- package/src/lib/server/paid-media-delivery.js.map +1 -0
- package/src/lib/server/pos-order.d.ts +54 -0
- package/src/lib/server/pos-order.js +1137 -0
- package/src/lib/server/pos-order.js.map +1 -0
- package/src/lib/server/process-abandoned.d.ts +54 -0
- package/src/lib/server/process-abandoned.js +222 -0
- package/src/lib/server/process-abandoned.js.map +1 -0
- package/src/lib/server/process-restock.d.ts +42 -0
- package/src/lib/server/process-restock.js +219 -0
- package/src/lib/server/process-restock.js.map +1 -0
- package/src/lib/server/product-card.d.ts +29 -0
- package/src/lib/server/product-card.js +54 -0
- package/src/lib/server/product-card.js.map +1 -0
- package/src/lib/server/product.d.ts +70 -0
- package/src/lib/server/product.js +105 -0
- package/src/lib/server/product.js.map +1 -0
- package/src/lib/server/promotion-hold.d.ts +144 -0
- package/src/lib/server/promotion-hold.js +174 -0
- package/src/lib/server/promotion-hold.js.map +1 -0
- package/src/lib/server/reconcile-stock.d.ts +106 -0
- package/src/lib/server/reconcile-stock.js +349 -0
- package/src/lib/server/reconcile-stock.js.map +1 -0
- package/src/lib/server/refund.d.ts +45 -0
- package/src/lib/server/refund.js +607 -0
- package/src/lib/server/refund.js.map +1 -0
- package/src/lib/server/related.d.ts +24 -0
- package/src/lib/server/related.js +104 -0
- package/src/lib/server/related.js.map +1 -0
- package/src/lib/server/reservation-availability.d.ts +23 -0
- package/src/lib/server/reservation-availability.js +111 -0
- package/src/lib/server/reservation-availability.js.map +1 -0
- package/src/lib/server/reserve-stock.d.ts +156 -0
- package/src/lib/server/reserve-stock.js +146 -0
- package/src/lib/server/reserve-stock.js.map +1 -0
- package/src/lib/server/reserve.d.ts +25 -0
- package/src/lib/server/reserve.js +426 -0
- package/src/lib/server/reserve.js.map +1 -0
- package/src/lib/server/restock-flag.d.ts +202 -0
- package/src/lib/server/restock-flag.js +449 -0
- package/src/lib/server/restock-flag.js.map +1 -0
- package/src/lib/server/reviews.d.ts +51 -0
- package/src/lib/server/reviews.js +132 -0
- package/src/lib/server/reviews.js.map +1 -0
- package/src/lib/server/site-page-enricher.d.ts +42 -0
- package/src/lib/server/site-page-enricher.js +149 -0
- package/src/lib/server/site-page-enricher.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +26 -0
- package/src/lib/server/site-page-resolver.js +223 -0
- package/src/lib/server/site-page-resolver.js.map +1 -0
- package/src/lib/server/stock-hold.d.ts +127 -0
- package/src/lib/server/stock-hold.js +258 -0
- package/src/lib/server/stock-hold.js.map +1 -0
- package/src/lib/server/storefront-tax-record.d.ts +22 -0
- package/src/lib/server/storefront-tax-record.js +218 -0
- package/src/lib/server/storefront-tax-record.js.map +1 -0
- package/src/lib/server/storefront-tax.d.ts +197 -0
- package/src/lib/server/storefront-tax.js +245 -0
- package/src/lib/server/storefront-tax.js.map +1 -0
- package/src/lib/server/stream.d.ts +25 -0
- package/src/lib/server/stream.js +191 -0
- package/src/lib/server/stream.js.map +1 -0
- package/src/lib/server/subscription-portal.d.ts +24 -0
- package/src/lib/server/subscription-portal.js +91 -0
- package/src/lib/server/subscription-portal.js.map +1 -0
- package/src/lib/server/supplier-outbox.d.ts +190 -0
- package/src/lib/server/supplier-outbox.js +342 -0
- package/src/lib/server/supplier-outbox.js.map +1 -0
- package/src/lib/server/supplier-update.d.ts +23 -0
- package/src/lib/server/supplier-update.js +289 -0
- package/src/lib/server/supplier-update.js.map +1 -0
- package/src/lib/server/tax-profile.d.ts +29 -0
- package/src/lib/server/tax-profile.js +40 -0
- package/src/lib/server/tax-profile.js.map +1 -0
- package/src/lib/server.d.ts +32 -0
- package/src/lib/server.js +311 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/site.d.ts +27 -0
- package/src/lib/site.js +134 -0
- package/src/lib/site.js.map +1 -0
- package/src/lib/utils/escape-html.d.ts +41 -0
- package/src/lib/utils/escape-html.js +41 -0
- package/src/lib/utils/escape-html.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/member-continue.d.ts +45 -0
- package/src/lib/utils/member-continue.js +49 -0
- package/src/lib/utils/member-continue.js.map +1 -0
- package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
- package/src/lib/utils/use-storefront-purchase-event.js +142 -0
- package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
19
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
+
import * as Aglyn from "@aglyn/aglyn";
|
|
21
|
+
import * as CommerceModel from "../../model/index.js";
|
|
22
|
+
import { CardDisplay } from "@aglyn/shared-ui-jsx";
|
|
23
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
24
|
+
import { Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, MenuItem, Stack, TextField, Typography } from "@mui/material";
|
|
25
|
+
import { collection, deleteDoc, doc, setDoc } from "firebase/firestore";
|
|
26
|
+
import { useCallback, useState } from "react";
|
|
27
|
+
import { useFirestore } from "@aglyn/tenant-feature-instance";
|
|
28
|
+
import { collectionPage, usePagedCollection, writeGuardedBySeed } from "@aglyn/tenant-feature-instance";
|
|
29
|
+
import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
|
|
30
|
+
import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
31
|
+
/**
|
|
32
|
+
* Discounts hub (AGL-305): code and automatic promotions with value,
|
|
33
|
+
* min-subtotal, schedule, and usage-limit controls, resolved at
|
|
34
|
+
* checkout/POS by the shared engine. Supersedes the simple coupons
|
|
35
|
+
* card (which keeps working for existing codes).
|
|
36
|
+
*/ export function DiscountsCard(props) {
|
|
37
|
+
var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;
|
|
38
|
+
const { hostId } = props;
|
|
39
|
+
const firestore = useFirestore();
|
|
40
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
41
|
+
const { status: discountsStatus, /**
|
|
42
|
+
* The row this dialog is seeded from is unconfirmed by the server
|
|
43
|
+
* (AGL-1358). `redemptions` is a LIVE counter the checkout engine
|
|
44
|
+
* increments, and editing a discount copies it out of the seed and
|
|
45
|
+
* writes it straight back — so a cached seed rolls the count backwards
|
|
46
|
+
* and hands out redemptions that were already spent.
|
|
47
|
+
*/ fromCache: discountsFromCache, rows: discounts, hasMore, page, setPage, pageSize, setPageSize } = usePagedCollection(/*
|
|
48
|
+
* SERVER-PAGED, and ordered (AGL-2501).
|
|
49
|
+
*
|
|
50
|
+
* `limit(100)` alone is answered in DOCUMENT-ID order and the ids are
|
|
51
|
+
* `createResourceUid()`, so the hundred were a pseudo-random sample of the
|
|
52
|
+
* shop's promotions — and the hundred-and-first was UNREACHABLE, because
|
|
53
|
+
* nothing rendered it and no control asked for more.
|
|
54
|
+
*
|
|
55
|
+
* The query can be paged here, unlike the cards carrying a duplicate-name
|
|
56
|
+
* check: a discount's identity is its document id, `code` is an ordinary
|
|
57
|
+
* field with no uniqueness test on this surface, and nothing on the card
|
|
58
|
+
* is computed from rows that are off the page.
|
|
59
|
+
*
|
|
60
|
+
* `collectionPage` orders on the document NAME. `orderBy('code')` is the
|
|
61
|
+
* tempting one and would be wrong twice: an AUTOMATIC promotion is stored
|
|
62
|
+
* with `code: null`, so ordering on it would hide every automatic discount
|
|
63
|
+
* the shop has, and a merchant reading "no automatic promotions" would be
|
|
64
|
+
* reading a query artifact.
|
|
65
|
+
*/ (pageLimit)=>collectionPage(collection(firestore, 'hosts', hostId, 'discounts'), pageLimit), [
|
|
66
|
+
firestore,
|
|
67
|
+
hostId
|
|
68
|
+
], {
|
|
69
|
+
idField: '$id'
|
|
70
|
+
});
|
|
71
|
+
const [draft, setDraft] = useState(null);
|
|
72
|
+
const handleSave = useCallback(async ()=>{
|
|
73
|
+
var _data_code;
|
|
74
|
+
if (!draft) return;
|
|
75
|
+
/**
|
|
76
|
+
* `$id` comes off with `id` (AGL-1374).
|
|
77
|
+
*
|
|
78
|
+
* The editor is seeded `{ id: discount.$id, ...discount }`, and that
|
|
79
|
+
* spread carries the listener's SYNTHETIC `$id` — `idField: '$id'`
|
|
80
|
+
* stamps the document id onto the in-memory row, where nothing persists
|
|
81
|
+
* it. Destructuring only `id` left `$id` in `data`, so every save wrote
|
|
82
|
+
* it into the stored document as a real field. Nothing reads it; it is
|
|
83
|
+
* the listener's bookkeeping leaking into storage, and once there no
|
|
84
|
+
* reader can tell it from a field the card meant to write.
|
|
85
|
+
*/ const seeded = draft;
|
|
86
|
+
const { id, $id: _syntheticId } = seeded, data = _object_without_properties_loose(seeded, [
|
|
87
|
+
"id",
|
|
88
|
+
"$id"
|
|
89
|
+
]);
|
|
90
|
+
const code = (_data_code = data.code) == null ? void 0 : _data_code.trim().toUpperCase().replace(/[^A-Z0-9_-]/g, '');
|
|
91
|
+
/**
|
|
92
|
+
* Refuse an EDIT whose seed the server never confirmed (AGL-1358).
|
|
93
|
+
*
|
|
94
|
+
* `merge: true` protects nothing here — `{...data}` carries every field
|
|
95
|
+
* of the seeded row, `redemptions` included, so it is written back
|
|
96
|
+
* whether or not anyone touched it. Under `persistentLocalCache` that
|
|
97
|
+
* seed can be arbitrarily old, and a redemption cap silently regains
|
|
98
|
+
* uses that buyers already spent.
|
|
99
|
+
*
|
|
100
|
+
* Only the edit path is guarded: a NEW discount is built from blanks at
|
|
101
|
+
* a fresh uid and can overwrite nothing.
|
|
102
|
+
*/ const verdict = await writeGuardedBySeed({
|
|
103
|
+
subject: 'discount',
|
|
104
|
+
unreadable: Boolean(id) && discountsStatus === 'error',
|
|
105
|
+
fromCache: Boolean(id) && discountsFromCache
|
|
106
|
+
}, async ()=>{
|
|
107
|
+
var _data_redemptions;
|
|
108
|
+
await setDoc(doc(firestore, 'hosts', hostId, 'discounts', id != null ? id : Aglyn.createResourceUid()), _extends({}, data, code ? {
|
|
109
|
+
code
|
|
110
|
+
} : {
|
|
111
|
+
code: null
|
|
112
|
+
}, {
|
|
113
|
+
enabled: data.enabled !== false,
|
|
114
|
+
redemptions: (_data_redemptions = data.redemptions) != null ? _data_redemptions : 0
|
|
115
|
+
}), {
|
|
116
|
+
merge: true
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
// Keep the dialog open with what was typed rather than failing silently.
|
|
120
|
+
if (!verdict.ok) {
|
|
121
|
+
return void enqueueSnackbar(verdict.message, {
|
|
122
|
+
variant: 'warning',
|
|
123
|
+
persist: false
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
setDraft(null);
|
|
127
|
+
enqueueSnackbar('Discount saved', {
|
|
128
|
+
variant: 'success',
|
|
129
|
+
persist: false
|
|
130
|
+
});
|
|
131
|
+
}, [
|
|
132
|
+
draft,
|
|
133
|
+
firestore,
|
|
134
|
+
hostId,
|
|
135
|
+
enqueueSnackbar,
|
|
136
|
+
discountsFromCache,
|
|
137
|
+
discountsStatus
|
|
138
|
+
]);
|
|
139
|
+
const describe = (discount)=>{
|
|
140
|
+
var _discount_valueCents;
|
|
141
|
+
const value = discount.kind === 'percent' ? `${discount.valuePct}% off` : discount.kind === 'fixed' ? `$${(((_discount_valueCents = discount.valueCents) != null ? _discount_valueCents : 0) / 100).toFixed(2)} off` : 'Free shipping';
|
|
142
|
+
const scopeCount = Array.isArray(discount.productIds) ? discount.productIds.length : 0;
|
|
143
|
+
const extras = [
|
|
144
|
+
// THE SCOPE, SAID OUT LOUD. A discount can cover named
|
|
145
|
+
// products rather than the catalog, and the card showed no sign of it —
|
|
146
|
+
// so a merchant could not tell a store-wide discount from a scoped one,
|
|
147
|
+
// and had no way to understand why a scoped one takes less off than the
|
|
148
|
+
// basket total. "Store-wide" is stated rather than left blank, because a
|
|
149
|
+
// silent absence is what a narrower scope would also look like.
|
|
150
|
+
scopeCount > 0 ? `${scopeCount} product${scopeCount === 1 ? '' : 's'} only` : 'store-wide',
|
|
151
|
+
discount.minSubtotalCents ? `min $${(discount.minSubtotalCents / 100).toFixed(0)}` : '',
|
|
152
|
+
// Held slots are NAMED, not folded into the used figure (AGL-2453). A
|
|
153
|
+
// live checkout now consumes a slot for as long as it can still be paid,
|
|
154
|
+
// so `redemptions` alone would show a cap of 100 sitting at 100 against
|
|
155
|
+
// 97 orders with nothing to explain the other three.
|
|
156
|
+
discount.maxRedemptions ? CommerceModel.promotionUsageLabel(discount, Date.now()) : ''
|
|
157
|
+
].filter(Boolean).join(' · ');
|
|
158
|
+
return `${value}${extras ? ` · ${extras}` : ''}`;
|
|
159
|
+
};
|
|
160
|
+
return /*#__PURE__*/ _jsxs(CardDisplay, {
|
|
161
|
+
header: 'Discounts',
|
|
162
|
+
help: pluginDocsHelp('commerceEndToEnd', {
|
|
163
|
+
anchor: '#4-what-checkout-does',
|
|
164
|
+
excerpt: 'Discount codes your customers type at your own checkout — not ' + `the coupons ${Aglyn.PLATFORM_BRAND_NAME} issues against your subscription.`
|
|
165
|
+
}),
|
|
166
|
+
contentGutterX: true,
|
|
167
|
+
contentGutterY: true,
|
|
168
|
+
children: [
|
|
169
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
170
|
+
spacing: 1,
|
|
171
|
+
children: [
|
|
172
|
+
discounts.length === 0 && page === 0 ? /*#__PURE__*/ _jsx(Typography, {
|
|
173
|
+
variant: "body2",
|
|
174
|
+
color: "text.secondary",
|
|
175
|
+
children: 'Codes buyers enter at checkout, or automatic promotions that ' + 'apply on their own.'
|
|
176
|
+
}) : discounts.map((discount)=>/*#__PURE__*/ _jsxs(Stack, {
|
|
177
|
+
direction: "row",
|
|
178
|
+
spacing: 1,
|
|
179
|
+
sx: {
|
|
180
|
+
alignItems: 'center'
|
|
181
|
+
},
|
|
182
|
+
children: [
|
|
183
|
+
/*#__PURE__*/ _jsx(Chip, {
|
|
184
|
+
label: discount.code || discount.name || 'Automatic',
|
|
185
|
+
size: "small",
|
|
186
|
+
variant: "outlined",
|
|
187
|
+
color: discount.code ? 'primary' : 'info'
|
|
188
|
+
}),
|
|
189
|
+
/*#__PURE__*/ _jsxs(Typography, {
|
|
190
|
+
variant: "body2",
|
|
191
|
+
sx: {
|
|
192
|
+
flex: 1
|
|
193
|
+
},
|
|
194
|
+
noWrap: true,
|
|
195
|
+
children: [
|
|
196
|
+
describe(discount),
|
|
197
|
+
discount.enabled === false ? ' · disabled' : ''
|
|
198
|
+
]
|
|
199
|
+
}),
|
|
200
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
201
|
+
size: "small",
|
|
202
|
+
onClick: ()=>setDraft(_extends({
|
|
203
|
+
id: discount.$id
|
|
204
|
+
}, discount)),
|
|
205
|
+
children: 'Edit'
|
|
206
|
+
}),
|
|
207
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
208
|
+
size: "small",
|
|
209
|
+
color: "error",
|
|
210
|
+
onClick: ()=>deleteDoc(doc(firestore, 'hosts', hostId, 'discounts', discount.$id)),
|
|
211
|
+
children: 'Delete'
|
|
212
|
+
})
|
|
213
|
+
]
|
|
214
|
+
}, discount.$id)),
|
|
215
|
+
discounts.length === 0 && page === 0 ? null : /*#__PURE__*/ _jsx(ListPagination, {
|
|
216
|
+
page: page,
|
|
217
|
+
pageSize: pageSize,
|
|
218
|
+
rowCount: discounts.length,
|
|
219
|
+
// No `count`: a server window does not know the collection's
|
|
220
|
+
// total, and `hasMore` is the probe row's answer rather than a
|
|
221
|
+
// comparison against the cap.
|
|
222
|
+
hasMore: hasMore,
|
|
223
|
+
onPageChange: setPage,
|
|
224
|
+
onPageSizeChange: setPageSize
|
|
225
|
+
}),
|
|
226
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
227
|
+
size: "small",
|
|
228
|
+
sx: {
|
|
229
|
+
alignSelf: 'flex-start'
|
|
230
|
+
},
|
|
231
|
+
onClick: ()=>setDraft({
|
|
232
|
+
id: null,
|
|
233
|
+
kind: 'percent',
|
|
234
|
+
valuePct: 10,
|
|
235
|
+
enabled: true
|
|
236
|
+
}),
|
|
237
|
+
children: 'Add discount'
|
|
238
|
+
})
|
|
239
|
+
]
|
|
240
|
+
}),
|
|
241
|
+
/*#__PURE__*/ _jsxs(Dialog, {
|
|
242
|
+
open: Boolean(draft),
|
|
243
|
+
onClose: ()=>setDraft(null),
|
|
244
|
+
maxWidth: "xs",
|
|
245
|
+
fullWidth: true,
|
|
246
|
+
children: [
|
|
247
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
248
|
+
children: (draft == null ? void 0 : draft.id) ? 'Edit discount' : 'New discount'
|
|
249
|
+
}),
|
|
250
|
+
/*#__PURE__*/ _jsxs(DialogContent, {
|
|
251
|
+
sx: {
|
|
252
|
+
display: 'flex',
|
|
253
|
+
flexDirection: 'column',
|
|
254
|
+
gap: 2
|
|
255
|
+
},
|
|
256
|
+
children: [
|
|
257
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
258
|
+
label: "Code (blank = automatic)",
|
|
259
|
+
value: (_ref = draft == null ? void 0 : draft.code) != null ? _ref : '',
|
|
260
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
261
|
+
code: event.target.value
|
|
262
|
+
}) : prev),
|
|
263
|
+
size: "small",
|
|
264
|
+
sx: {
|
|
265
|
+
mt: 1
|
|
266
|
+
},
|
|
267
|
+
placeholder: "SAVE10"
|
|
268
|
+
}),
|
|
269
|
+
!(draft == null ? void 0 : draft.code) ? /*#__PURE__*/ _jsx(TextField, {
|
|
270
|
+
label: "Promotion name",
|
|
271
|
+
value: (_ref1 = draft == null ? void 0 : draft.name) != null ? _ref1 : '',
|
|
272
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
273
|
+
name: event.target.value
|
|
274
|
+
}) : prev),
|
|
275
|
+
size: "small",
|
|
276
|
+
placeholder: "Summer sale"
|
|
277
|
+
}) : null,
|
|
278
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
279
|
+
direction: "row",
|
|
280
|
+
spacing: 1,
|
|
281
|
+
children: [
|
|
282
|
+
/*#__PURE__*/ _jsxs(TextField, {
|
|
283
|
+
label: "Type",
|
|
284
|
+
value: (_ref2 = draft == null ? void 0 : draft.kind) != null ? _ref2 : 'percent',
|
|
285
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
286
|
+
kind: event.target.value
|
|
287
|
+
}) : prev),
|
|
288
|
+
size: "small",
|
|
289
|
+
select: true,
|
|
290
|
+
sx: {
|
|
291
|
+
minWidth: 150
|
|
292
|
+
},
|
|
293
|
+
children: [
|
|
294
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
295
|
+
value: "percent",
|
|
296
|
+
children: 'Percent off'
|
|
297
|
+
}),
|
|
298
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
299
|
+
value: "fixed",
|
|
300
|
+
children: 'Fixed amount off'
|
|
301
|
+
}),
|
|
302
|
+
/*#__PURE__*/ _jsx(MenuItem, {
|
|
303
|
+
value: "free_shipping",
|
|
304
|
+
children: 'Free shipping'
|
|
305
|
+
})
|
|
306
|
+
]
|
|
307
|
+
}),
|
|
308
|
+
(draft == null ? void 0 : draft.kind) === 'percent' ? /*#__PURE__*/ _jsx(TextField, {
|
|
309
|
+
label: "%",
|
|
310
|
+
value: (_ref3 = draft == null ? void 0 : draft.valuePct) != null ? _ref3 : '',
|
|
311
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
312
|
+
valuePct: Math.min(100, Math.max(0, Number(event.target.value) || 0))
|
|
313
|
+
}) : prev),
|
|
314
|
+
size: "small",
|
|
315
|
+
sx: {
|
|
316
|
+
width: 90
|
|
317
|
+
},
|
|
318
|
+
slotProps: {
|
|
319
|
+
htmlInput: {
|
|
320
|
+
inputMode: 'numeric'
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}) : null,
|
|
324
|
+
(draft == null ? void 0 : draft.kind) === 'fixed' ? /*#__PURE__*/ _jsx(TextField, {
|
|
325
|
+
label: "$ off",
|
|
326
|
+
value: (draft == null ? void 0 : draft.valueCents) != null ? draft.valueCents / 100 : '',
|
|
327
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
328
|
+
valueCents: Math.round((Number(event.target.value) || 0) * 100)
|
|
329
|
+
}) : prev),
|
|
330
|
+
size: "small",
|
|
331
|
+
sx: {
|
|
332
|
+
width: 110
|
|
333
|
+
},
|
|
334
|
+
slotProps: {
|
|
335
|
+
htmlInput: {
|
|
336
|
+
inputMode: 'decimal'
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}) : null
|
|
340
|
+
]
|
|
341
|
+
}),
|
|
342
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
343
|
+
direction: "row",
|
|
344
|
+
spacing: 1,
|
|
345
|
+
children: [
|
|
346
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
347
|
+
label: "Min subtotal ($)",
|
|
348
|
+
placeholder: "None",
|
|
349
|
+
value: (draft == null ? void 0 : draft.minSubtotalCents) != null ? draft.minSubtotalCents / 100 : '',
|
|
350
|
+
onChange: (event)=>{
|
|
351
|
+
const raw = event.target.value.trim();
|
|
352
|
+
setDraft((prev)=>prev ? _extends({}, prev, {
|
|
353
|
+
minSubtotalCents: raw === '' ? undefined : Math.round((Number(raw) || 0) * 100)
|
|
354
|
+
}) : prev);
|
|
355
|
+
},
|
|
356
|
+
size: "small",
|
|
357
|
+
slotProps: {
|
|
358
|
+
htmlInput: {
|
|
359
|
+
inputMode: 'decimal'
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}),
|
|
363
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
364
|
+
label: "Max uses",
|
|
365
|
+
placeholder: "Unlimited",
|
|
366
|
+
value: (_ref4 = draft == null ? void 0 : draft.maxRedemptions) != null ? _ref4 : '',
|
|
367
|
+
onChange: (event)=>{
|
|
368
|
+
const raw = event.target.value.trim();
|
|
369
|
+
setDraft((prev)=>prev ? _extends({}, prev, {
|
|
370
|
+
maxRedemptions: raw === '' ? undefined : Math.max(1, Math.round(Number(raw)))
|
|
371
|
+
}) : prev);
|
|
372
|
+
},
|
|
373
|
+
size: "small",
|
|
374
|
+
slotProps: {
|
|
375
|
+
htmlInput: {
|
|
376
|
+
inputMode: 'numeric'
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
]
|
|
381
|
+
}),
|
|
382
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
383
|
+
direction: "row",
|
|
384
|
+
spacing: 1,
|
|
385
|
+
children: [
|
|
386
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
387
|
+
label: "Starts",
|
|
388
|
+
type: "date",
|
|
389
|
+
value: (draft == null ? void 0 : draft.startAtMs) ? new Date(draft.startAtMs).toISOString().slice(0, 10) : '',
|
|
390
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
391
|
+
startAtMs: event.target.value ? Date.parse(`${event.target.value}T00:00:00Z`) : undefined
|
|
392
|
+
}) : prev),
|
|
393
|
+
size: "small",
|
|
394
|
+
fullWidth: true,
|
|
395
|
+
slotProps: {
|
|
396
|
+
inputLabel: {
|
|
397
|
+
shrink: true
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}),
|
|
401
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
402
|
+
label: "Ends",
|
|
403
|
+
type: "date",
|
|
404
|
+
value: (draft == null ? void 0 : draft.endAtMs) ? new Date(draft.endAtMs).toISOString().slice(0, 10) : '',
|
|
405
|
+
onChange: (event)=>setDraft((prev)=>prev ? _extends({}, prev, {
|
|
406
|
+
endAtMs: event.target.value ? Date.parse(`${event.target.value}T23:59:59Z`) : undefined
|
|
407
|
+
}) : prev),
|
|
408
|
+
size: "small",
|
|
409
|
+
fullWidth: true,
|
|
410
|
+
slotProps: {
|
|
411
|
+
inputLabel: {
|
|
412
|
+
shrink: true
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
})
|
|
416
|
+
]
|
|
417
|
+
})
|
|
418
|
+
]
|
|
419
|
+
}),
|
|
420
|
+
/*#__PURE__*/ _jsxs(DialogActions, {
|
|
421
|
+
children: [
|
|
422
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
423
|
+
onClick: ()=>setDraft(null),
|
|
424
|
+
children: 'Cancel'
|
|
425
|
+
}),
|
|
426
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
427
|
+
variant: "contained",
|
|
428
|
+
color: "primary",
|
|
429
|
+
disabled: (draft == null ? void 0 : draft.kind) === 'percent' && !(((_ref5 = draft == null ? void 0 : draft.valuePct) != null ? _ref5 : 0) > 0) || (draft == null ? void 0 : draft.kind) === 'fixed' && !(((_ref6 = draft == null ? void 0 : draft.valueCents) != null ? _ref6 : 0) > 0),
|
|
430
|
+
onClick: handleSave,
|
|
431
|
+
children: 'Save'
|
|
432
|
+
})
|
|
433
|
+
]
|
|
434
|
+
})
|
|
435
|
+
]
|
|
436
|
+
})
|
|
437
|
+
]
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
DiscountsCard.displayName = 'DiscountsCard';
|
|
441
|
+
export default DiscountsCard;
|
|
442
|
+
|
|
443
|
+
//# sourceMappingURL=discounts-card.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/discounts-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport * as CommerceModel from '../../model'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport {\n collection,\n deleteDoc,\n doc,\n setDoc,\n} from 'firebase/firestore'\nimport { useCallback, useState } from 'react'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport {\n collectionPage,\n usePagedCollection,\n writeGuardedBySeed,\n} from '@aglyn/tenant-feature-instance'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\n\nexport interface DiscountsCardProps {\n hostId: string\n}\n\n/**\n * Discounts hub (AGL-305): code and automatic promotions with value,\n * min-subtotal, schedule, and usage-limit controls, resolved at\n * checkout/POS by the shared engine. Supersedes the simple coupons\n * card (which keeps working for existing codes).\n */\nexport function DiscountsCard(props: DiscountsCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const {\n status: discountsStatus,\n /**\n * The row this dialog is seeded from is unconfirmed by the server\n * (AGL-1358). `redemptions` is a LIVE counter the checkout engine\n * increments, and editing a discount copies it out of the seed and\n * writes it straight back — so a cached seed rolls the count backwards\n * and hands out redemptions that were already spent.\n */\n fromCache: discountsFromCache,\n rows: discounts,\n hasMore,\n page,\n setPage,\n pageSize,\n setPageSize,\n } = usePagedCollection<any>(\n /*\n * SERVER-PAGED, and ordered (AGL-2501).\n *\n * `limit(100)` alone is answered in DOCUMENT-ID order and the ids are\n * `createResourceUid()`, so the hundred were a pseudo-random sample of the\n * shop's promotions — and the hundred-and-first was UNREACHABLE, because\n * nothing rendered it and no control asked for more.\n *\n * The query can be paged here, unlike the cards carrying a duplicate-name\n * check: a discount's identity is its document id, `code` is an ordinary\n * field with no uniqueness test on this surface, and nothing on the card\n * is computed from rows that are off the page.\n *\n * `collectionPage` orders on the document NAME. `orderBy('code')` is the\n * tempting one and would be wrong twice: an AUTOMATIC promotion is stored\n * with `code: null`, so ordering on it would hide every automatic discount\n * the shop has, and a merchant reading \"no automatic promotions\" would be\n * reading a query artifact.\n */\n (pageLimit) =>\n collectionPage(\n collection(firestore, 'hosts', hostId, 'discounts'),\n pageLimit,\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const [draft, setDraft] = useState<\n (Partial<CommerceModel.HostDiscount> & { id: string | null }) | null\n >(null)\n\n const handleSave = useCallback(async () => {\n if (!draft) return\n /**\n * `$id` comes off with `id` (AGL-1374).\n *\n * The editor is seeded `{ id: discount.$id, ...discount }`, and that\n * spread carries the listener's SYNTHETIC `$id` — `idField: '$id'`\n * stamps the document id onto the in-memory row, where nothing persists\n * it. Destructuring only `id` left `$id` in `data`, so every save wrote\n * it into the stored document as a real field. Nothing reads it; it is\n * the listener's bookkeeping leaking into storage, and once there no\n * reader can tell it from a field the card meant to write.\n */\n const seeded = draft as typeof draft & { $id?: string }\n const { id, $id: _syntheticId, ...data } = seeded\n const code = data.code?.trim().toUpperCase().replace(/[^A-Z0-9_-]/g, '')\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * `merge: true` protects nothing here — `{...data}` carries every field\n * of the seeded row, `redemptions` included, so it is written back\n * whether or not anyone touched it. Under `persistentLocalCache` that\n * seed can be arbitrarily old, and a redemption cap silently regains\n * uses that buyers already spent.\n *\n * Only the edit path is guarded: a NEW discount is built from blanks at\n * a fresh uid and can overwrite nothing.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'discount',\n unreadable: Boolean(id) && discountsStatus === 'error',\n fromCache: Boolean(id) && discountsFromCache,\n },\n async () => {\n await setDoc(\n doc(\n firestore,\n 'hosts',\n hostId,\n 'discounts',\n id ?? Aglyn.createResourceUid(),\n ),\n {\n ...data,\n ...(code ? { code } : { code: null }),\n enabled: data.enabled !== false,\n redemptions: data.redemptions ?? 0,\n },\n { merge: true },\n )\n },\n )\n // Keep the dialog open with what was typed rather than failing silently.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n setDraft(null)\n enqueueSnackbar('Discount saved', { variant: 'success', persist: false })\n }, [\n draft,\n firestore,\n hostId,\n enqueueSnackbar,\n discountsFromCache,\n discountsStatus,\n ])\n\n const describe = (discount: any) => {\n const value =\n discount.kind === 'percent'\n ? `${discount.valuePct}% off`\n : discount.kind === 'fixed'\n ? `$${((discount.valueCents ?? 0) / 100).toFixed(2)} off`\n : 'Free shipping'\n const scopeCount = Array.isArray(discount.productIds)\n ? discount.productIds.length\n : 0\n const extras = [\n // THE SCOPE, SAID OUT LOUD. A discount can cover named\n // products rather than the catalog, and the card showed no sign of it —\n // so a merchant could not tell a store-wide discount from a scoped one,\n // and had no way to understand why a scoped one takes less off than the\n // basket total. \"Store-wide\" is stated rather than left blank, because a\n // silent absence is what a narrower scope would also look like.\n scopeCount > 0\n ? `${scopeCount} product${scopeCount === 1 ? '' : 's'} only`\n : 'store-wide',\n discount.minSubtotalCents\n ? `min $${(discount.minSubtotalCents / 100).toFixed(0)}`\n : '',\n // Held slots are NAMED, not folded into the used figure (AGL-2453). A\n // live checkout now consumes a slot for as long as it can still be paid,\n // so `redemptions` alone would show a cap of 100 sitting at 100 against\n // 97 orders with nothing to explain the other three.\n discount.maxRedemptions\n ? CommerceModel.promotionUsageLabel(discount, Date.now())\n : '',\n ]\n .filter(Boolean)\n .join(' · ')\n return `${value}${extras ? ` · ${extras}` : ''}`\n }\n\n return (\n <CardDisplay\n header={'Discounts'}\n help={pluginDocsHelp('commerceEndToEnd', {\n anchor: '#4-what-checkout-does',\n excerpt:\n 'Discount codes your customers type at your own checkout — not ' +\n `the coupons ${Aglyn.PLATFORM_BRAND_NAME} issues against your subscription.`,\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1}>\n {discounts.length === 0 && page === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Codes buyers enter at checkout, or automatic promotions that ' +\n 'apply on their own.'}\n </Typography>\n ) : (\n discounts.map((discount: any) => (\n <Stack\n key={discount.$id}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center' }}\n >\n <Chip\n label={discount.code || discount.name || 'Automatic'}\n size=\"small\"\n variant=\"outlined\"\n color={discount.code ? 'primary' : 'info'}\n />\n <Typography variant=\"body2\" sx={{ flex: 1 }} noWrap>\n {describe(discount)}\n {discount.enabled === false ? ' · disabled' : ''}\n </Typography>\n <Button\n size=\"small\"\n onClick={() => setDraft({ id: discount.$id, ...discount })}\n >\n {'Edit'}\n </Button>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() =>\n deleteDoc(\n doc(firestore, 'hosts', hostId, 'discounts', discount.$id),\n )\n }\n >\n {'Delete'}\n </Button>\n </Stack>\n ))\n )}\n {discounts.length === 0 && page === 0 ? null : (\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={discounts.length}\n // No `count`: a server window does not know the collection's\n // total, and `hasMore` is the probe row's answer rather than a\n // comparison against the cap.\n hasMore={hasMore}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n )}\n <Button\n size=\"small\"\n sx={{ alignSelf: 'flex-start' }}\n onClick={() =>\n setDraft({ id: null, kind: 'percent', valuePct: 10, enabled: true })\n }\n >\n {'Add discount'}\n </Button>\n </Stack>\n <Dialog\n open={Boolean(draft)}\n onClose={() => setDraft(null)}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{draft?.id ? 'Edit discount' : 'New discount'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label=\"Code (blank = automatic)\"\n value={draft?.code ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, code: event.target.value } : prev,\n )\n }\n size=\"small\"\n sx={{ mt: 1 }}\n placeholder=\"SAVE10\"\n />\n {!draft?.code ? (\n <TextField\n label=\"Promotion name\"\n value={draft?.name ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, name: event.target.value } : prev,\n )\n }\n size=\"small\"\n placeholder=\"Summer sale\"\n />\n ) : null}\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Type\"\n value={draft?.kind ?? 'percent'}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? { ...prev, kind: event.target.value as CommerceModel.DiscountKind }\n : prev,\n )\n }\n size=\"small\"\n select\n sx={{ minWidth: 150 }}\n >\n <MenuItem value=\"percent\">{'Percent off'}</MenuItem>\n <MenuItem value=\"fixed\">{'Fixed amount off'}</MenuItem>\n <MenuItem value=\"free_shipping\">{'Free shipping'}</MenuItem>\n </TextField>\n {draft?.kind === 'percent' ? (\n <TextField\n label=\"%\"\n value={draft?.valuePct ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n valuePct: Math.min(\n 100,\n Math.max(0, Number(event.target.value) || 0),\n ),\n }\n : prev,\n )\n }\n size=\"small\"\n sx={{ width: 90 }}\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n ) : null}\n {draft?.kind === 'fixed' ? (\n <TextField\n label=\"$ off\"\n value={\n draft?.valueCents != null ? draft.valueCents / 100 : ''\n }\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n valueCents: Math.round(\n (Number(event.target.value) || 0) * 100,\n ),\n }\n : prev,\n )\n }\n size=\"small\"\n sx={{ width: 110 }}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n ) : null}\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Min subtotal ($)\"\n placeholder=\"None\"\n value={\n draft?.minSubtotalCents != null\n ? draft.minSubtotalCents / 100\n : ''\n }\n onChange={(event) => {\n const raw = event.target.value.trim()\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n minSubtotalCents:\n raw === ''\n ? undefined\n : Math.round((Number(raw) || 0) * 100),\n }\n : prev,\n )\n }}\n size=\"small\"\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n <TextField\n label=\"Max uses\"\n placeholder=\"Unlimited\"\n value={draft?.maxRedemptions ?? ''}\n onChange={(event) => {\n const raw = event.target.value.trim()\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n maxRedemptions:\n raw === ''\n ? undefined\n : Math.max(1, Math.round(Number(raw))),\n }\n : prev,\n )\n }}\n size=\"small\"\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Starts\"\n type=\"date\"\n value={\n draft?.startAtMs\n ? new Date(draft.startAtMs).toISOString().slice(0, 10)\n : ''\n }\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n startAtMs: event.target.value\n ? Date.parse(`${event.target.value}T00:00:00Z`)\n : undefined,\n }\n : prev,\n )\n }\n size=\"small\"\n fullWidth\n slotProps={{ inputLabel: { shrink: true } }}\n />\n <TextField\n label=\"Ends\"\n type=\"date\"\n value={\n draft?.endAtMs\n ? new Date(draft.endAtMs).toISOString().slice(0, 10)\n : ''\n }\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n endAtMs: event.target.value\n ? Date.parse(`${event.target.value}T23:59:59Z`)\n : undefined,\n }\n : prev,\n )\n }\n size=\"small\"\n fullWidth\n slotProps={{ inputLabel: { shrink: true } }}\n />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDraft(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n (draft?.kind === 'percent' && !((draft?.valuePct ?? 0) > 0)) ||\n (draft?.kind === 'fixed' && !((draft?.valueCents ?? 0) > 0))\n }\n onClick={handleSave}\n >\n {'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nDiscountsCard.displayName = 'DiscountsCard'\n\nexport default DiscountsCard\n"],"names":["Aglyn","CommerceModel","CardDisplay","useSnackbar","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Typography","collection","deleteDoc","doc","setDoc","useCallback","useState","useFirestore","collectionPage","usePagedCollection","writeGuardedBySeed","ListPagination","pluginDocsHelp","DiscountsCard","props","hostId","firestore","enqueueSnackbar","status","discountsStatus","fromCache","discountsFromCache","rows","discounts","hasMore","page","setPage","pageSize","setPageSize","pageLimit","idField","draft","setDraft","handleSave","data","seeded","id","$id","_syntheticId","code","trim","toUpperCase","replace","verdict","subject","unreadable","Boolean","createResourceUid","enabled","redemptions","merge","ok","message","variant","persist","describe","discount","value","kind","valuePct","valueCents","toFixed","scopeCount","Array","isArray","productIds","length","extras","minSubtotalCents","maxRedemptions","promotionUsageLabel","Date","now","filter","join","header","help","anchor","excerpt","PLATFORM_BRAND_NAME","contentGutterX","contentGutterY","spacing","color","map","direction","sx","alignItems","label","name","size","flex","noWrap","onClick","rowCount","onPageChange","onPageSizeChange","alignSelf","open","onClose","maxWidth","fullWidth","display","flexDirection","gap","onChange","event","prev","target","mt","placeholder","select","minWidth","Math","min","max","Number","width","slotProps","htmlInput","inputMode","round","raw","undefined","type","startAtMs","toISOString","slice","parse","inputLabel","shrink","endAtMs","disabled","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { OrgFeatureFlags } from '@aglyn/aglyn';
|
|
2
|
+
import { type HelpTipContent } from '@aglyn/shared-ui-jsx';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
export interface CommerceEntitlementState {
|
|
5
|
+
/** The plan doc has settled. NEVER refuse before this is true. */
|
|
6
|
+
ready: boolean;
|
|
7
|
+
entitled: boolean;
|
|
8
|
+
/** Console billing route, or undefined before the org slug resolves. */
|
|
9
|
+
upgradeHref: string | undefined;
|
|
10
|
+
/** Cheapest plan carrying the feature — "Business". */
|
|
11
|
+
planLabel: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The three-state entitlement read every commerce console surface needs
|
|
15
|
+
* (AGL-2080), factored out of the copy-pasted pair that
|
|
16
|
+
* `CommerceAnalyticsCard` and `CommerceGlanceCard` grew in AGL-2056.
|
|
17
|
+
*
|
|
18
|
+
* Three states, not two. `checkEntitlement(undefined)` resolves the FREE
|
|
19
|
+
* tier rather than "unknown", so a surface that refuses on `!entitled`
|
|
20
|
+
* alone shows a paying customer an upgrade prompt for the render or two
|
|
21
|
+
* their org doc is in flight. `ready` is the difference, and it is why this
|
|
22
|
+
* returns a struct rather than a boolean — a boolean is the API that caused
|
|
23
|
+
* the bug.
|
|
24
|
+
*
|
|
25
|
+
* `planLabel` comes from `planGrantingFeature`, derived from
|
|
26
|
+
* `PLAN_ENTITLEMENTS` on every call, so the upsell can never name a tier
|
|
27
|
+
* that no longer carries the feature.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useCommerceEntitlement(hostId: string | undefined, feature: keyof OrgFeatureFlags): CommerceEntitlementState;
|
|
30
|
+
export interface EntitlementUpsellProps {
|
|
31
|
+
/** What the feature is and what it does, in the operator's terms. */
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
planLabel: string | undefined;
|
|
34
|
+
upgradeHref: string | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The locked-state notice: what the feature is, which plan carries it, and
|
|
38
|
+
* one click to the plan grid.
|
|
39
|
+
*
|
|
40
|
+
* The plan name is not decoration. "This is a paid feature" is a dead end;
|
|
41
|
+
* "this is on Business" plus an Upgrade button is the upgrade path AGL-1859
|
|
42
|
+
* asks to keep prominent and one-click. Always `AppLink` — a MUI `href`
|
|
43
|
+
* bypasses the client router and full-reloads the console.
|
|
44
|
+
*/
|
|
45
|
+
export declare function EntitlementUpsell(props: EntitlementUpsellProps): import("react").JSX.Element;
|
|
46
|
+
export interface EntitlementGatedCardProps {
|
|
47
|
+
hostId: string;
|
|
48
|
+
feature: keyof OrgFeatureFlags;
|
|
49
|
+
header: string;
|
|
50
|
+
/**
|
|
51
|
+
* Help affordance for the two branches this component renders itself
|
|
52
|
+
* (AGL-2213).
|
|
53
|
+
*
|
|
54
|
+
* Required, not optional. The entitled branch renders `children`, which is
|
|
55
|
+
* the real card and carries its own help; the branches rendered HERE are
|
|
56
|
+
* "checking your plan" and the refusal — and the refusal is the one a
|
|
57
|
+
* reader reaches precisely because they do not have what it takes. That is
|
|
58
|
+
* the branch AGL-2130 found carrying no explanation on two console cards,
|
|
59
|
+
* and an optional prop would let it happen again silently.
|
|
60
|
+
*/
|
|
61
|
+
help: HelpTipContent;
|
|
62
|
+
/** Locked-state copy: what this does, so the upsell sells something. */
|
|
63
|
+
upsell: ReactNode;
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A whole console card behind an entitlement (AGL-2080).
|
|
68
|
+
*
|
|
69
|
+
* The refusal happens BEFORE the operator can configure anything, which is
|
|
70
|
+
* the entire point: five commerce features were fully configurable by an
|
|
71
|
+
* unentitled org and only failed at checkout — a refusal delivered to the
|
|
72
|
+
* buyer instead of the operator. A warning after configuration would be the
|
|
73
|
+
* same defect with better manners.
|
|
74
|
+
*/
|
|
75
|
+
export declare function EntitlementGatedCard(props: EntitlementGatedCardProps): import("react").JSX.Element;
|
|
76
|
+
export default EntitlementGatedCard;
|