@aglyn/plugins-commerce 1.0.0-beta.231 → 1.0.0-beta.233
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/package.json +13 -13
- package/src/lib/components/cart-extras.d.ts +6 -0
- package/src/lib/components/cart-extras.js +4 -1
- package/src/lib/components/cart-extras.js.map +1 -1
- package/src/lib/components/cart-fulfillment.d.ts +117 -0
- package/src/lib/components/cart-fulfillment.js +367 -0
- package/src/lib/components/cart-fulfillment.js.map +1 -0
- package/src/lib/components/cart.js +52 -10
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +42 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/catalog-organization-card.component.js +1 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.js +42 -11
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/local-delivery-settings-card.component.d.ts +37 -0
- package/src/lib/components/console/local-delivery-settings-card.component.js +542 -0
- package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -0
- package/src/lib/components/console/locations-card.component.js +177 -3
- package/src/lib/components/console/locations-card.component.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +10 -0
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-local-fulfillment-panel.component.d.ts +44 -0
- package/src/lib/components/console/order-local-fulfillment-panel.component.js +265 -0
- package/src/lib/components/console/order-local-fulfillment-panel.component.js.map +1 -0
- package/src/lib/components/console/order-offline-notice.component.d.ts +12 -0
- package/src/lib/components/console/order-offline-notice.component.js +53 -0
- package/src/lib/components/console/order-offline-notice.component.js.map +1 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.d.ts +35 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.js +222 -0
- package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-api.d.ts +24 -1
- package/src/lib/components/console/pos/pos-api.js +13 -0
- package/src/lib/components/console/pos/pos-api.js.map +1 -1
- package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +12 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js +10 -8
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-kiosk-queue.component.d.ts +22 -0
- package/src/lib/components/console/pos/pos-kiosk-queue.component.js +168 -0
- package/src/lib/components/console/pos/pos-kiosk-queue.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +18 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js +116 -1
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +8 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js +77 -18
- package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
- package/src/lib/components/console/pos/use-pos-display.d.ts +5 -2
- package/src/lib/components/console/pos/use-pos-display.js +3 -2
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
- package/src/lib/components/console/pos-devices-card.component.js +2 -2
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-display/pairing-screen.d.ts +5 -2
- package/src/lib/components/console/pos-display/pairing-screen.js +7 -5
- package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -1
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +7 -1
- package/src/lib/components/console/pos-display/pos-display-api.js +7 -2
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.d.ts +41 -0
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.js +275 -0
- package/src/lib/components/console/pos-kiosk/kiosk-checkout.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.d.ts +32 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.js +344 -0
- package/src/lib/components/console/pos-kiosk/kiosk-menu.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.d.ts +12 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.js +257 -0
- package/src/lib/components/console/pos-kiosk/kiosk-staff.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.d.ts +114 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js +189 -0
- package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js.map +1 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.d.ts +16 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js +80 -0
- package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js.map +1 -0
- package/src/lib/components/console/pos-kiosk-page.component.d.ts +28 -0
- package/src/lib/components/console/pos-kiosk-page.component.js +791 -0
- package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.d.ts +44 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.js +69 -0
- package/src/lib/components/console/pos-offline/pos-offline-api.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.d.ts +7 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.js +135 -0
- package/src/lib/components/console/pos-offline/pos-offline-banner.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.d.ts +32 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js +287 -0
- package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js.map +1 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.d.ts +63 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.js +145 -0
- package/src/lib/components/console/pos-offline/pos-offline-store.js.map +1 -0
- package/src/lib/components/console/pos-offline/register-offline.d.ts +24 -0
- package/src/lib/components/console/pos-offline/register-offline.js +24 -0
- package/src/lib/components/console/pos-offline/register-offline.js.map +1 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.d.ts +85 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.js +542 -0
- package/src/lib/components/console/pos-offline/use-pos-offline.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +72 -17
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +228 -51
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-zones.d.ts +23 -0
- package/src/lib/components/console/pos-zones.js +31 -0
- package/src/lib/components/console/pos-zones.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +10 -64
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +46 -30
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/shipping-settings-card.component.js +1 -1
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
- package/src/lib/components/console/stock-movements-card.component.js +48 -16
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
- package/src/lib/components/console/store-zones.d.ts +8 -1
- package/src/lib/components/console/store-zones.js +11 -1
- package/src/lib/components/console/store-zones.js.map +1 -1
- package/src/lib/components/console/storefront-tax-summary-card.component.js +1 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -1
- package/src/lib/components/order-status.js +66 -0
- package/src/lib/components/order-status.js.map +1 -1
- package/src/lib/components/product-detail.js +42 -15
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/constants/local-fulfillment-list-query.d.ts +48 -0
- package/src/lib/constants/local-fulfillment-list-query.js +84 -0
- package/src/lib/constants/local-fulfillment-list-query.js.map +1 -0
- package/src/lib/constants/orders-list-query.d.ts +7 -2
- package/src/lib/constants/orders-list-query.js +89 -8
- package/src/lib/constants/orders-list-query.js.map +1 -1
- package/src/lib/constants/pos-shift-list-query.d.ts +22 -0
- package/src/lib/constants/pos-shift-list-query.js +115 -0
- package/src/lib/constants/pos-shift-list-query.js.map +1 -0
- package/src/lib/constants/product-list-query.d.ts +6 -1
- package/src/lib/constants/product-list-query.js +77 -8
- package/src/lib/constants/product-list-query.js.map +1 -1
- package/src/lib/constants/stock-movement-query.d.ts +3 -2
- package/src/lib/constants/stock-movement-query.js +52 -8
- package/src/lib/constants/stock-movement-query.js.map +1 -1
- package/src/lib/declarations.server.js +21 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/buyer-notifications.d.ts +5 -3
- package/src/lib/model/buyer-notifications.js +25 -4
- package/src/lib/model/buyer-notifications.js.map +1 -1
- package/src/lib/model/commerce-orders.d.ts +103 -1
- package/src/lib/model/commerce-orders.js +2 -1
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-kiosk.d.ts +175 -0
- package/src/lib/model/commerce-pos-kiosk.js +147 -0
- package/src/lib/model/commerce-pos-kiosk.js.map +1 -0
- package/src/lib/model/commerce-pos-offline.d.ts +234 -0
- package/src/lib/model/commerce-pos-offline.js +301 -0
- package/src/lib/model/commerce-pos-offline.js.map +1 -0
- package/src/lib/model/commerce-pos-ops.d.ts +16 -6
- package/src/lib/model/commerce-pos-ops.js +12 -4
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +13 -1
- package/src/lib/model/commerce-pos.js +5 -4
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-stock-holds.d.ts +24 -3
- package/src/lib/model/commerce-stock-holds.js +26 -8
- package/src/lib/model/commerce-stock-holds.js.map +1 -1
- package/src/lib/model/commerce.d.ts +7 -1
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +5 -0
- package/src/lib/model/index.js +5 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/local-fulfillment-settings.d.ts +178 -0
- package/src/lib/model/local-fulfillment-settings.js +361 -0
- package/src/lib/model/local-fulfillment-settings.js.map +1 -0
- package/src/lib/model/order-list-fields.d.ts +10 -1
- package/src/lib/model/order-list-fields.js +1 -0
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/order-local-fulfillment.d.ts +131 -0
- package/src/lib/model/order-local-fulfillment.js +125 -0
- package/src/lib/model/order-local-fulfillment.js.map +1 -0
- package/src/lib/model/order-shipping-export.js +4 -0
- package/src/lib/model/order-shipping-export.js.map +1 -1
- package/src/lib/model/order-status-view.d.ts +20 -1
- package/src/lib/model/order-status-view.js +60 -6
- package/src/lib/model/order-status-view.js.map +1 -1
- package/src/lib/model/product-write.d.ts +186 -0
- package/src/lib/model/product-write.js +116 -0
- package/src/lib/model/product-write.js.map +1 -0
- package/src/lib/plugin-config.js +6 -2
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +11 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/pos-kiosk-config.d.ts +26 -0
- package/src/lib/pos-kiosk-config.js +59 -0
- package/src/lib/pos-kiosk-config.js.map +1 -0
- package/src/lib/server/api-v1/openapi.js +8 -0
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/api-v1/order-view.d.ts +19 -0
- package/src/lib/server/api-v1/order-view.js +35 -0
- package/src/lib/server/api-v1/order-view.js.map +1 -1
- package/src/lib/server/billing-webhook.js +238 -87
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cart-checkout.d.ts +2 -0
- package/src/lib/server/cart-checkout.js +173 -13
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/channel-order-updates.d.ts +50 -0
- package/src/lib/server/channel-order-updates.js +290 -0
- package/src/lib/server/channel-order-updates.js.map +1 -0
- package/src/lib/server/channel-orders.d.ts +85 -0
- package/src/lib/server/channel-orders.js +543 -0
- package/src/lib/server/channel-orders.js.map +1 -0
- package/src/lib/server/checkout-extras.js +18 -4
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +71 -14
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/local-fulfillment-status.d.ts +86 -0
- package/src/lib/server/local-fulfillment-status.js +379 -0
- package/src/lib/server/local-fulfillment-status.js.map +1 -0
- package/src/lib/server/local-fulfillment.d.ts +190 -0
- package/src/lib/server/local-fulfillment.js +580 -0
- package/src/lib/server/local-fulfillment.js.map +1 -0
- package/src/lib/server/membership-register.js +3 -1
- package/src/lib/server/membership-register.js.map +1 -1
- package/src/lib/server/order-notifications.js +61 -0
- package/src/lib/server/order-notifications.js.map +1 -1
- package/src/lib/server/pos-display.d.ts +27 -1
- package/src/lib/server/pos-display.js +50 -9
- package/src/lib/server/pos-display.js.map +1 -1
- package/src/lib/server/pos-kiosk-principal.d.ts +29 -0
- package/src/lib/server/pos-kiosk-principal.js +42 -0
- package/src/lib/server/pos-kiosk-principal.js.map +1 -0
- package/src/lib/server/pos-kiosk.d.ts +54 -0
- package/src/lib/server/pos-kiosk.js +972 -0
- package/src/lib/server/pos-kiosk.js.map +1 -0
- package/src/lib/server/pos-offline-sync.d.ts +85 -0
- package/src/lib/server/pos-offline-sync.js +765 -0
- package/src/lib/server/pos-offline-sync.js.map +1 -0
- package/src/lib/server/pos-order.js +22 -4
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.d.ts +6 -0
- package/src/lib/server/pos-payment.js +225 -6
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-print.js +5 -0
- package/src/lib/server/pos-print.js.map +1 -1
- package/src/lib/server/pos-return.js +27 -0
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/pos-sale.d.ts +6 -0
- package/src/lib/server/pos-sale.js +2 -0
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-shift.js +8 -1
- package/src/lib/server/pos-shift.js.map +1 -1
- package/src/lib/server/product-catalog.js +5 -1
- package/src/lib/server/product-catalog.js.map +1 -1
- package/src/lib/server/product-drafts.d.ts +5 -1
- package/src/lib/server/product-drafts.js +3 -3
- package/src/lib/server/product-drafts.js.map +1 -1
- package/src/lib/server/product-writer.d.ts +19 -0
- package/src/lib/server/product-writer.js +261 -0
- package/src/lib/server/product-writer.js.map +1 -0
- package/src/lib/server/products-write.d.ts +61 -0
- package/src/lib/server/products-write.js +375 -0
- package/src/lib/server/products-write.js.map +1 -0
- package/src/lib/server/refund.js +3 -0
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/stock-hold.d.ts +9 -1
- package/src/lib/server/stock-hold.js +15 -7
- package/src/lib/server/stock-hold.js.map +1 -1
- package/src/lib/server.js +21 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/tenant-emails.js +161 -0
- package/src/lib/tenant-emails.js.map +1 -1
- package/src/lib/testing/memory-firestore.d.ts +16 -3
- package/src/lib/testing/memory-firestore.js +11 -3
- package/src/lib/testing/memory-firestore.js.map +1 -1
- package/src/lib/transfer/products.server.d.ts +5 -0
- package/src/lib/transfer/products.server.js +2 -2
- package/src/lib/transfer/products.server.js.map +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/cart-fulfillment.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\nimport Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport FormControl from '@mui/material/FormControl'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport FormLabel from '@mui/material/FormLabel'\nimport MenuItem from '@mui/material/MenuItem'\nimport Radio from '@mui/material/Radio'\nimport RadioGroup from '@mui/material/RadioGroup'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport type { PickupLocationOption } from '../model/local-fulfillment-settings'\nimport { pickupReadyWithinLabel } from '../model/local-fulfillment-settings'\n\n/**\n * How the shopper receives the order (AGL-3624): shipped, picked up at one of\n * the store's locations, or brought by the store's own driver. Asked at the\n * cart because that is where the store still decides what the checkout\n * offers; `POST /api/commerce/local-fulfillment-options` answers what this\n * store and this basket can have, and the checkout decides the fee, the\n * minimum and the window again from the store's settings — nothing shown\n * here is trusted.\n *\n * A store with no pickup location and no local delivery gets an empty answer\n * and draws nothing: its cart is exactly what it was.\n */\n\nexport interface CartDeliveryWindow {\n id: string\n startMs: number\n endMs: number\n label: string\n}\n\nexport interface CartDeliveryQuote {\n zoneId?: string\n zoneName?: string\n feeCents?: number\n minimumCents?: number\n freeOverCents?: number\n shortfallCents?: number\n unavailable?: string\n}\n\nexport interface CartFulfillmentOptions {\n pickup: PickupLocationOption[]\n delivery: {\n country: string\n instructions?: string\n needsAddress: boolean\n windows: CartDeliveryWindow[]\n quote?: CartDeliveryQuote\n } | null\n /** Whether the store can text the buyer about the pickup or delivery. */\n texts?: boolean\n}\n\nexport type CartFulfillmentMethod = 'shipping' | 'pickup' | 'local_delivery'\n\nconst EMPTY: CartFulfillmentOptions = { pickup: [], delivery: null }\n\nexport function useCartFulfillment(\n hostId: string | undefined,\n cartSignature: string,\n /**\n * A product's Buy button asks for that product rather than the cart; `null`\n * asks nothing (a subscription, a download).\n */\n buyNow?: { productId: string; variantId?: string; quantity: number } | null,\n) {\n const buyNowKey = buyNow === undefined ? '' : JSON.stringify(buyNow)\n const [options, setOptions] = useState<CartFulfillmentOptions>(EMPTY)\n const [method, setMethod] = useState<CartFulfillmentMethod>('shipping')\n const [locationId, setLocationId] = useState('')\n const [postalCode, setPostalCode] = useState('')\n const [line1, setLine1] = useState('')\n const [windowId, setWindowId] = useState('')\n const [textPhone, setTextPhone] = useState('')\n const [round, setRound] = useState(0)\n // The postal code and street the quote below was asked for, settled after\n // the shopper stops typing so a keystroke is not a request.\n const [asked, setAsked] = useState({ postalCode: '', line1: '' })\n useEffect(() => {\n const timer = setTimeout(() => setAsked({ postalCode: postalCode.trim(), line1: line1.trim() }), 400)\n return () => clearTimeout(timer)\n }, [postalCode, line1])\n\n useEffect(() => {\n if (!hostId || cartSignature === '[]' || buyNow === null) {\n setOptions(EMPTY)\n return\n }\n let live = true\n const wantsQuote = method === 'local_delivery' && asked.postalCode.length >= 3\n fetch('/api/commerce/local-fulfillment-options', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n hostId,\n ...(buyNow ? buyNow : {}),\n ...(wantsQuote ? { postalCode: asked.postalCode } : {}),\n ...(wantsQuote && asked.line1 ? { address: { line1: asked.line1, postalCode: asked.postalCode } } : {}),\n }),\n })\n .then((response) => (response.ok ? response.json() : EMPTY))\n .then((payload: CartFulfillmentOptions) => {\n if (!live) return\n const next: CartFulfillmentOptions = {\n pickup: Array.isArray(payload?.pickup) ? payload.pickup : [],\n delivery: payload?.delivery ?? null,\n texts: Boolean(payload?.texts),\n }\n setOptions(next)\n // A choice the store no longer offers falls back to shipping.\n setMethod((prior) =>\n (prior === 'pickup' && !next.pickup.length) || (prior === 'local_delivery' && !next.delivery)\n ? 'shipping'\n : prior,\n )\n setLocationId((prior) =>\n next.pickup.some((location) => location.id === prior) ? prior : (next.pickup[0]?.id ?? ''),\n )\n setWindowId((prior) =>\n next.delivery?.windows.some((window) => window.id === prior) ? prior : '',\n )\n })\n .catch(() => live && setOptions(EMPTY))\n return () => {\n live = false\n }\n // `buyNow` is read through its key.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hostId, cartSignature, round, method, asked, buyNowKey])\n\n const offered = options.pickup.length > 0 || Boolean(options.delivery)\n const quote = options.delivery?.quote\n const deliverable = Boolean(quote && !quote.unavailable && !(quote.shortfallCents && quote.shortfallCents > 0))\n /** What the checkout is sent; `null` for a shipped order. */\n const phone = options.texts && textPhone.trim() ? { textPhone: textPhone.trim() } : {}\n const request = useMemo(() => {\n if (method === 'pickup' && locationId) return { method: 'pickup' as const, locationId, ...phone }\n if (method === 'local_delivery') {\n return {\n method: 'local_delivery' as const,\n ...phone,\n postalCode: postalCode.trim(),\n ...(windowId ? { windowStartMs: Number(windowId) } : {}),\n ...(line1.trim() ? { address: { line1: line1.trim(), postalCode: postalCode.trim() } } : {}),\n }\n }\n return null\n // `phone` is derived from the two values listed.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [method, locationId, postalCode, windowId, line1, textPhone, options.texts])\n /** Whether the choice is complete enough to check out with. */\n const ready =\n method === 'shipping' ||\n (method === 'pickup' && Boolean(locationId)) ||\n // The quote is the server's answer for what was typed: a zone that\n // reaches it and an order that meets its minimum.\n (method === 'local_delivery' && Boolean(postalCode.trim()) && Boolean(windowId) && deliverable)\n const signature = JSON.stringify(request)\n const reload = useCallback(() => setRound((value) => value + 1), [])\n return {\n options,\n offered,\n method,\n setMethod,\n locationId,\n setLocationId,\n postalCode,\n setPostalCode,\n line1,\n setLine1,\n windowId,\n setWindowId,\n textPhone,\n setTextPhone,\n request,\n ready,\n signature,\n reload,\n }\n}\n\nexport type CartFulfillmentState = ReturnType<typeof useCartFulfillment>\n\nexport function CartFulfillmentChoice(props: {\n state: CartFulfillmentState\n formatCents: (cents: number) => string\n}) {\n const { state, formatCents } = props\n const { options, method } = state\n if (!state.offered) return null\n const location = options.pickup.find((entry) => entry.id === state.locationId)\n const delivery = options.delivery\n const quote = delivery?.quote\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>\n <FormControl>\n <FormLabel id=\"cart-fulfillment-method\">\n <Typography variant=\"subtitle2\" component=\"span\">\n {'How do you want your order?'}\n </Typography>\n </FormLabel>\n <RadioGroup\n aria-labelledby=\"cart-fulfillment-method\"\n value={method}\n onChange={(event) => state.setMethod(event.target.value as CartFulfillmentMethod)}\n >\n <FormControlLabel value=\"shipping\" control={<Radio size=\"small\" />} label=\"Ship it\" />\n {options.pickup.length ? (\n <FormControlLabel\n value=\"pickup\"\n control={<Radio size=\"small\" />}\n label={options.pickup.length === 1 ? `Pick up at ${options.pickup[0].name}` : 'Pick up in store'}\n />\n ) : null}\n {delivery ? (\n <FormControlLabel value=\"local_delivery\" control={<Radio size=\"small\" />} label=\"Local delivery\" />\n ) : null}\n </RadioGroup>\n </FormControl>\n {method === 'pickup' ? (\n <>\n {options.pickup.length > 1 ? (\n <TextField\n select\n label=\"Pickup location\"\n value={state.locationId}\n onChange={(event) => state.setLocationId(event.target.value)}\n size=\"small\"\n >\n {options.pickup.map((entry) => (\n <MenuItem key={entry.id} value={entry.id}>\n {entry.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {location ? (\n <Box>\n {location.address ? (\n <Typography variant=\"body2\">{location.address}</Typography>\n ) : null}\n {location.hours ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" sx={{ whiteSpace: 'pre-line' }}>\n {location.hours}\n </Typography>\n ) : null}\n {location.readyWithinMinutes ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {`${pickupReadyWithinLabel(location.readyWithinMinutes)}. We’ll email you when it’s ready.`}\n </Typography>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {'We’ll email you when it’s ready.'}\n </Typography>\n )}\n {location.instructions ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {location.instructions}\n </Typography>\n ) : null}\n </Box>\n ) : null}\n </>\n ) : null}\n {method !== 'shipping' && options.texts ? (\n <TextField\n label=\"Mobile number (optional)\"\n value={state.textPhone}\n onChange={(event) => state.setTextPhone(event.target.value)}\n size=\"small\"\n helperText={\n method === 'pickup'\n ? 'We’ll text you when your order is ready'\n : 'We’ll text you when your order is on its way'\n }\n slotProps={{ htmlInput: { autoComplete: 'tel', inputMode: 'tel', maxLength: 24 } }}\n />\n ) : null}\n {method === 'local_delivery' && delivery ? (\n <>\n <TextField\n label=\"Postal code\"\n value={state.postalCode}\n onChange={(event) => state.setPostalCode(event.target.value)}\n size=\"small\"\n slotProps={{ htmlInput: { autoComplete: 'shipping postal-code', maxLength: 12 } }}\n />\n {delivery.needsAddress ? (\n <TextField\n label=\"Street address\"\n value={state.line1}\n onChange={(event) => state.setLine1(event.target.value)}\n size=\"small\"\n helperText=\"Delivery depends on the distance from the store\"\n slotProps={{ htmlInput: { autoComplete: 'shipping address-line1', maxLength: 120 } }}\n />\n ) : null}\n {quote?.unavailable ? <Alert severity=\"info\">{quote.unavailable}</Alert> : null}\n {quote && !quote.unavailable ? (\n quote.shortfallCents && quote.shortfallCents > 0 ? (\n <Alert severity=\"info\">\n {`Delivery needs an order of at least ${formatCents(quote.minimumCents ?? 0)}. ` +\n `Add ${formatCents(quote.shortfallCents)} more.`}\n </Alert>\n ) : (\n <Typography variant=\"body2\">\n {quote.feeCents\n ? `Delivery: ${formatCents(quote.feeCents)}`\n : 'Delivery: free'}\n {quote.freeOverCents && quote.feeCents\n ? ` (free over ${formatCents(quote.freeOverCents)})`\n : ''}\n </Typography>\n )\n ) : null}\n {delivery.windows.length ? (\n <TextField\n select\n label=\"Delivery time\"\n value={state.windowId}\n onChange={(event) => state.setWindowId(event.target.value)}\n size=\"small\"\n >\n {delivery.windows.map((window) => (\n <MenuItem key={window.id} value={window.id}>\n {window.label}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <Alert severity=\"info\">{'No delivery times are open right now.'}</Alert>\n )}\n {delivery.instructions ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {delivery.instructions}\n </Typography>\n ) : null}\n </>\n ) : null}\n </Box>\n )\n}\n"],"names":["Alert","Box","FormControl","FormControlLabel","FormLabel","MenuItem","Radio","RadioGroup","TextField","Typography","useCallback","useEffect","useMemo","useState","pickupReadyWithinLabel","EMPTY","pickup","delivery","useCartFulfillment","hostId","cartSignature","buyNow","options","buyNowKey","undefined","JSON","stringify","setOptions","method","setMethod","locationId","setLocationId","postalCode","setPostalCode","line1","setLine1","windowId","setWindowId","textPhone","setTextPhone","round","setRound","asked","setAsked","timer","setTimeout","trim","clearTimeout","live","wantsQuote","length","fetch","headers","body","address","then","response","ok","json","payload","next","Array","isArray","texts","Boolean","prior","some","location","id","windows","window","catch","offered","quote","deliverable","unavailable","shortfallCents","phone","request","windowStartMs","Number","ready","signature","reload","value","CartFulfillmentChoice","props","state","formatCents","find","entry","sx","display","flexDirection","gap","variant","component","aria-labelledby","onChange","event","target","control","size","label","name","select","map","hours","color","whiteSpace","readyWithinMinutes","instructions","helperText","slotProps","htmlInput","autoComplete","inputMode","maxLength","needsAddress","severity","minimumCents","feeCents","freeOverCents"],"mappings":"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"}
|
|
@@ -39,6 +39,7 @@ import { Suspense, forwardRef, lazy, useCallback, useEffect, useMemo, useRef, us
|
|
|
39
39
|
import { StorefrontPaymentElementFallback } from "./storefront-payment-element-fallback.js";
|
|
40
40
|
import { CheckoutReturnNotice } from "./checkout-return-notice.js";
|
|
41
41
|
import { CartExtras, useCartExtras } from "./cart-extras.js";
|
|
42
|
+
import { CartFulfillmentChoice, useCartFulfillment } from "./cart-fulfillment.js";
|
|
42
43
|
/**
|
|
43
44
|
* The Payment Element (AGL-1944), lazily. Stripe.js and its React wrapper are
|
|
44
45
|
* a large dependency and the flag is OFF, so a static import would ship the
|
|
@@ -80,6 +81,8 @@ function CartLines(props) {
|
|
|
80
81
|
const [email, setEmail] = useState('');
|
|
81
82
|
const [optIn, setOptIn] = useState(false);
|
|
82
83
|
const [giftCard, setGiftCard] = useState('');
|
|
84
|
+
// A rewards or referral code (AGL-3640), asked only where the store takes one.
|
|
85
|
+
const [creditCode, setCreditCode] = useState('');
|
|
83
86
|
// Where the parcel is going (AGL-1721). Asked ONLY when the server says it
|
|
84
87
|
// cannot price shipping without it — a merchant with one zone, one
|
|
85
88
|
// rest-of-world zone, or no shipping at all never sees this field, which is
|
|
@@ -186,6 +189,8 @@ function CartLines(props) {
|
|
|
186
189
|
// Optional lines another plugin offers (AGL-3635), asked while the cart is shown.
|
|
187
190
|
const extras = useCartExtras(hostId, cartSignature);
|
|
188
191
|
const extrasSignature = extras.chosenIds.join(',');
|
|
192
|
+
// Shipped, picked up, or the store's own delivery (AGL-3624).
|
|
193
|
+
const fulfillment = useCartFulfillment(hostId, cartSignature);
|
|
189
194
|
useEffect(()=>{
|
|
190
195
|
attemptKey.current = '';
|
|
191
196
|
}, [
|
|
@@ -193,9 +198,11 @@ function CartLines(props) {
|
|
|
193
198
|
email,
|
|
194
199
|
coupon,
|
|
195
200
|
giftCard,
|
|
201
|
+
creditCode,
|
|
196
202
|
shipTo,
|
|
197
203
|
shipPostal,
|
|
198
|
-
extrasSignature
|
|
204
|
+
extrasSignature,
|
|
205
|
+
fulfillment.signature
|
|
199
206
|
]);
|
|
200
207
|
const handleCheckout = useCallback(async ()=>{
|
|
201
208
|
if (status === 'sending') return;
|
|
@@ -226,12 +233,16 @@ function CartLines(props) {
|
|
|
226
233
|
couponCode: coupon.trim()
|
|
227
234
|
} : {}, giftCard.trim() ? {
|
|
228
235
|
giftCardCode: giftCard.trim()
|
|
229
|
-
} : {},
|
|
236
|
+
} : {}, creditCode.trim() && extras.credits.length ? {
|
|
237
|
+
creditCode: creditCode.trim()
|
|
238
|
+
} : {}, shipTo && !fulfillment.request ? {
|
|
230
239
|
shippingCountry: shipTo
|
|
231
|
-
} : {}, shipPostal.trim() ? {
|
|
240
|
+
} : {}, shipPostal.trim() && !fulfillment.request ? {
|
|
232
241
|
shippingPostalCode: shipPostal.trim()
|
|
233
242
|
} : {}, extras.chosenIds.length ? {
|
|
234
243
|
extras: extras.chosenIds
|
|
244
|
+
} : {}, fulfillment.request ? {
|
|
245
|
+
fulfillment: fulfillment.request
|
|
235
246
|
} : {}))
|
|
236
247
|
});
|
|
237
248
|
const payload = await response.json().catch(()=>({}));
|
|
@@ -313,6 +324,15 @@ function CartLines(props) {
|
|
|
313
324
|
setStatus('error');
|
|
314
325
|
return;
|
|
315
326
|
}
|
|
327
|
+
// The pickup location or delivery time went away while the cart was
|
|
328
|
+
// open (AGL-3624): ask again and let the shopper choose.
|
|
329
|
+
if (payload == null ? void 0 : payload.fulfillmentChanged) {
|
|
330
|
+
var _ref5;
|
|
331
|
+
fulfillment.reload();
|
|
332
|
+
setMessage(String((_ref5 = payload == null ? void 0 : payload.error) != null ? _ref5 : ''));
|
|
333
|
+
setStatus('error');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
316
336
|
if (isPaymentsNotConfigured(response.status)) {
|
|
317
337
|
setMessage(storefrontPaymentsNotConfiguredText());
|
|
318
338
|
setStatus('unconfigured');
|
|
@@ -322,13 +342,13 @@ function CartLines(props) {
|
|
|
322
342
|
// price this cart until it knows one (AGL-1721). Reveal the field and
|
|
323
343
|
// let the shopper answer; a store that never sends this never shows it.
|
|
324
344
|
if (payload == null ? void 0 : payload.needsShippingCountry) {
|
|
325
|
-
var
|
|
345
|
+
var _ref6;
|
|
326
346
|
var _payload_shippingCountries;
|
|
327
347
|
if (payload == null ? void 0 : payload.needsShippingPostalCode) setAskPostal(true);
|
|
328
348
|
setShipCountries(((_payload_shippingCountries = payload.shippingCountries) == null ? void 0 : _payload_shippingCountries.length) ? payload.shippingCountries : [
|
|
329
349
|
...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES
|
|
330
350
|
]);
|
|
331
|
-
setMessage(String((
|
|
351
|
+
setMessage(String((_ref6 = payload == null ? void 0 : payload.error) != null ? _ref6 : ''));
|
|
332
352
|
// An unserved destination is a real refusal and reads as one; being
|
|
333
353
|
// asked the first time is not.
|
|
334
354
|
setStatus(shipTo ? 'error' : 'ask');
|
|
@@ -352,12 +372,16 @@ function CartLines(props) {
|
|
|
352
372
|
email,
|
|
353
373
|
optIn,
|
|
354
374
|
giftCard,
|
|
375
|
+
creditCode,
|
|
355
376
|
shipTo,
|
|
356
377
|
shipPostal,
|
|
357
378
|
status,
|
|
358
379
|
siteFetch,
|
|
359
380
|
extras.chosenIds,
|
|
360
|
-
extras.reload
|
|
381
|
+
extras.reload,
|
|
382
|
+
extras.credits.length,
|
|
383
|
+
fulfillment.request,
|
|
384
|
+
fulfillment.reload
|
|
361
385
|
]);
|
|
362
386
|
if (!cart || cart.lines.length === 0) {
|
|
363
387
|
return /*#__PURE__*/ _jsx(Typography, {
|
|
@@ -487,10 +511,14 @@ function CartLines(props) {
|
|
|
487
511
|
onToggle: extras.toggle,
|
|
488
512
|
formatCents: usd
|
|
489
513
|
}),
|
|
514
|
+
/*#__PURE__*/ _jsx(CartFulfillmentChoice, {
|
|
515
|
+
state: fulfillment,
|
|
516
|
+
formatCents: usd
|
|
517
|
+
}),
|
|
490
518
|
/*#__PURE__*/ _jsx(Typography, {
|
|
491
519
|
variant: "caption",
|
|
492
520
|
color: "text.secondary",
|
|
493
|
-
children: 'Shipping and taxes are calculated at checkout.'
|
|
521
|
+
children: fulfillment.method === 'shipping' ? 'Shipping and taxes are calculated at checkout.' : 'Taxes are calculated at checkout.'
|
|
494
522
|
}),
|
|
495
523
|
/*#__PURE__*/ _jsx(TextField, {
|
|
496
524
|
label: "Email",
|
|
@@ -528,7 +556,20 @@ function CartLines(props) {
|
|
|
528
556
|
})
|
|
529
557
|
]
|
|
530
558
|
}) : null,
|
|
531
|
-
|
|
559
|
+
extras.credits.length ? // Drawn wherever the store takes a code, coupon field or not: a
|
|
560
|
+
// member was emailed theirs and comes here to spend it (AGL-3640).
|
|
561
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
562
|
+
label: `${extras.credits[0].label} code`,
|
|
563
|
+
value: creditCode,
|
|
564
|
+
onChange: (event)=>setCreditCode(event.target.value),
|
|
565
|
+
size: "small",
|
|
566
|
+
slotProps: {
|
|
567
|
+
htmlInput: {
|
|
568
|
+
'data-testid': 'cart-credit-code'
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}) : null,
|
|
572
|
+
shipCountries && fulfillment.method === 'shipping' ? /*#__PURE__*/ _jsx(TextField, {
|
|
532
573
|
select: true,
|
|
533
574
|
label: "Ship to",
|
|
534
575
|
value: shipTo,
|
|
@@ -543,7 +584,7 @@ function CartLines(props) {
|
|
|
543
584
|
}, code);
|
|
544
585
|
})
|
|
545
586
|
}) : null,
|
|
546
|
-
askPostal ? /*#__PURE__*/ _jsx(TextField, {
|
|
587
|
+
askPostal && fulfillment.method === 'shipping' ? /*#__PURE__*/ _jsx(TextField, {
|
|
547
588
|
label: "Postal code",
|
|
548
589
|
value: shipPostal,
|
|
549
590
|
onChange: (event)=>setShipPostal(event.target.value),
|
|
@@ -571,7 +612,8 @@ function CartLines(props) {
|
|
|
571
612
|
// 501, so the control latches off rather than inviting a retry that
|
|
572
613
|
// cannot succeed (AGL-2019).
|
|
573
614
|
status === 'unconfigured' || // Asked but unanswered: the server would only refuse again.
|
|
574
|
-
shipCountries !== null && !shipTo || askPostal && !shipPostal.trim(),
|
|
615
|
+
fulfillment.method === 'shipping' && shipCountries !== null && !shipTo || fulfillment.method === 'shipping' && askPostal && !shipPostal.trim() || // Pickup needs a location, delivery a zone and a time (AGL-3624).
|
|
616
|
+
!fulfillment.ready,
|
|
575
617
|
onClick: handleCheckout,
|
|
576
618
|
children: status === 'sending' ? // place (AGL-1944).
|
|
577
619
|
nativeCheckout ? 'Opening…' : 'Redirecting…' : checkoutLabel || 'Checkout'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/cart.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\nimport * as Aglyn from '@aglyn/aglyn'\nimport {\n buildBeginCheckoutParams,\n buildViewCartParams,\n trackEvent,\n trackEventBeforeNavigation,\n type AnalyticsItem,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { isPaymentsNotConfigured } from '@aglyn/aglyn/app-utils/payments-configured'\nimport { storefrontPaymentsNotConfiguredText } from '../constants/storefront-payments'\nimport * as CommerceModel from '../model'\nimport { mdiCartOutline } from '@aglyn/shared-data-mdi'\nimport Alert from '@mui/material/Alert'\nimport Badge from '@mui/material/Badge'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Checkbox from '@mui/material/Checkbox'\nimport Drawer from '@mui/material/Drawer'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport IconButton from '@mui/material/IconButton'\nimport MenuItem from '@mui/material/MenuItem'\nimport SvgIcon from '@mui/material/SvgIcon'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport {\n Suspense,\n forwardRef,\n lazy,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { StorefrontPaymentElementFallback } from './storefront-payment-element-fallback'\nimport { CheckoutReturnNotice } from './checkout-return-notice'\nimport { CartExtras, useCartExtras } from './cart-extras'\n\n/**\n * The Payment Element (AGL-1944), lazily. Stripe.js and its React wrapper are\n * a large dependency and the flag is OFF, so a static import would ship the\n * whole SDK in the bundle of every page carrying a cart — which is most pages\n * on a storefront — to serve a path no shopper currently reaches.\n */\nconst StorefrontPaymentElement = lazy(() =>\n import('./storefront-payment-element').then((module) => ({\n default: module.StorefrontPaymentElement,\n })),\n)\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport { useStorefrontPurchaseEvent } from '../utils/use-storefront-purchase-event'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'cart'\n\n/** Blocks dispatch this after mutating the cart so badges refresh. */\nexport const CART_UPDATED_EVENT = 'aglyn:cart-updated'\n\nexport interface CartProps {\n /** 'button' = app-bar icon + drawer; 'inline' = full cart in place. */\n variant?: 'button' | 'inline'\n checkoutLabel?: string\n /** Show the coupon-code field above checkout. */\n showCoupon?: boolean\n emptyText?: string\n}\n\ninterface CartLineView {\n productId: string\n variantId?: string\n quantity: number\n name: string\n variantLabel?: string\n unitAmountCents: number\n imageUrl?: string\n unavailable?: boolean\n}\n\ninterface CartView {\n lines: CartLineView[]\n count: number\n subtotalCents: number\n}\n\nconst usd = (cents: number) => `$${(cents / 100).toFixed(2)}`\n\n/**\n * The cart's lines as GA4 `items`.\n *\n * One mapping for every event this file sends — `view_cart` and both\n * `begin_checkout` branches — because the `item_id` is what joins them into a\n * single per-product funnel with the `view_item` and `add_to_cart` the product\n * blocks send. Three hand-written copies of the same map are three chances for\n * one step to start reporting a variant id, or a name, or a different price\n * basis, and a funnel whose steps disagree about the product silently reports\n * a drop that never happened.\n */\nfunction cartAnalyticsItems(cart: CartView | null): AnalyticsItem[] {\n return (cart?.lines ?? []).map((line) => ({\n item_id: line.productId,\n item_name: line.name,\n price: line.unitAmountCents / 100,\n quantity: line.quantity,\n }))\n}\n\nfunction CartLines(props: {\n hostId: string\n cart: CartView | null\n showCoupon?: boolean\n checkoutLabel?: string\n emptyText?: string\n onMutate: (body: Record<string, unknown>) => Promise<void>\n}) {\n const { hostId, cart, showCoupon, checkoutLabel, emptyText, onMutate } =\n props\n const siteFetch = Aglyn.useSiteFetch()\n const [coupon, setCoupon] = useState('')\n const [email, setEmail] = useState('')\n const [optIn, setOptIn] = useState(false)\n const [giftCard, setGiftCard] = useState('')\n // Where the parcel is going (AGL-1721). Asked ONLY when the server says it\n // cannot price shipping without it — a merchant with one zone, one\n // rest-of-world zone, or no shipping at all never sees this field, which is\n // the common configuration. `null` is \"not asked\", so the field appearing is\n // itself the server's answer rather than a guess made here.\n const [shipTo, setShipTo] = useState('')\n const [shipCountries, setShipCountries] = useState<string[] | null>(null)\n // Live carrier rates price by postal code (AGL-3612): asked only when the\n // store prices that way and the server says so.\n const [shipPostal, setShipPostal] = useState('')\n const [askPostal, setAskPostal] = useState(false)\n // `paused` is its own state, not an `error` with gentler words (AGL-1511):\n // the two need different severities, and a shopper told in red that\n // checkout failed does not read the sentence explaining it did not. `ask` is\n // the same argument again: being asked for a destination is not a failure.\n // `unconfigured` is the third instance (AGL-2019): a store with no Stripe key\n // answers 501, and before this that fell through to the error tail below and\n // rendered RED. It is also the only one of the five that is TERMINAL — the\n // others can succeed on a retry, this one cannot until the operator acts, so\n // it latches the buy control off instead of inviting another click.\n const [status, setStatus] = useState<\n 'idle' | 'sending' | 'error' | 'paused' | 'ask' | 'unconfigured'\n >('idle')\n const [message, setMessage] = useState('')\n /**\n * The in-page checkout session (AGL-1944). Null unless the server chose\n * native mode, which needs both the release flag and a publishable key.\n */\n const [nativeCheckout, setNativeCheckout] = useState<{\n clientSecret: string\n publishableKey: string\n /** The wallets the merchant hid (AGL-3629). */\n wallets?: CommerceModel.StorefrontCheckoutWallets\n } | null>(null)\n /**\n * In-progress quantity edits, keyed by line, as the raw field text\n * (AGL-1772). The field used to POST /api/commerce/cart on every\n * keystroke — typing \"100\" was three Firestore writes, and clearing the\n * field to retype passed through `\"\"` → 0, which is the REMOVE path, so a\n * select-all-and-retype could delete the line mid-edit (and the response\n * replacing `cart` state then fought the input).\n *\n * The repo convention for quantity inputs is local state committed on an\n * explicit settle — the PDP's Qty field (product-detail.tsx) holds\n * `useState` and sends nothing until the buy click, and besigner\n * attributes commit on blur. So: keystrokes only edit the draft; blur or\n * Enter commits ONE write; an empty or unparsable draft is a pending\n * state that reverts to the server's quantity, never a 0-as-remove. A\n * genuine remove still works both ways — the ✕ button, and typing an\n * actual 0 then leaving the field.\n */\n const [quantityDrafts, setQuantityDrafts] = useState<Record<string, string>>(\n {},\n )\n const lineKey = (line: CartLineView) =>\n `${line.productId}:${line.variantId ?? ''}`\n const commitQuantity = (line: CartLineView) => {\n const key = lineKey(line)\n const draft = quantityDrafts[key]\n if (draft === undefined) return\n // Drops the draft, but only if it is still THIS one — a keystroke that\n // lands while the write is in flight starts a new edit, and clearing it\n // here would erase what the shopper is typing.\n const settle = () =>\n setQuantityDrafts((drafts) => {\n if (drafts[key] !== draft) return drafts\n const { [key]: _settled, ...rest } = drafts\n return rest\n })\n // `Number('')` is 0 — exactly the misreading that turned a cleared\n // field into a remove. Empty means \"no answer\": show the server's\n // quantity again and write nothing. NaN (letters) reverts the same way.\n if (draft.trim() === '') return settle()\n const parsed = Math.round(Number(draft))\n if (!Number.isFinite(parsed)) return settle()\n const quantity = Math.max(0, parsed)\n // A settled value equal to the server's is not an edit.\n if (quantity === line.quantity) return settle()\n // The draft keeps rendering until the response lands, so the field does\n // not flash the superseded quantity during the round-trip; the server's\n // answer (via the replaced `cart`) takes over when it arrives.\n void onMutate({\n action: 'set',\n productId: line.productId,\n variantId: line.variantId,\n quantity,\n }).finally(settle)\n }\n\n /**\n * Idempotency key for ONE checkout attempt (AGL-1697).\n *\n * Minted lazily on the first checkout click, retired whenever the attempt\n * changes shape — different lines, codes, email or destination are a\n * different checkout. Keyed off a CONTENT signature of the lines rather\n * than the `cart` object, whose identity changes on every refetch: retiring\n * on identity would hand a genuine retry a fresh key, which is exactly the\n * double-session this exists to prevent.\n */\n const attemptKey = useRef('')\n const cartSignature = useMemo(\n () =>\n JSON.stringify(\n (cart?.lines ?? []).map((line) => [\n line.productId,\n line.variantId ?? '',\n line.quantity,\n ]),\n ),\n [cart],\n )\n // Optional lines another plugin offers (AGL-3635), asked while the cart is shown.\n const extras = useCartExtras(hostId, cartSignature)\n const extrasSignature = extras.chosenIds.join(',')\n useEffect(() => {\n attemptKey.current = ''\n }, [cartSignature, email, coupon, giftCard, shipTo, shipPostal, extrasSignature])\n\n const handleCheckout = useCallback(async () => {\n if (status === 'sending') return\n setStatus('sending')\n setMessage('')\n if (!attemptKey.current) {\n attemptKey.current =\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n try {\n const response = await siteFetch('/api/commerce/cart-checkout', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // Stable across a retry of THIS attempt (AGL-1697), so a\n // double-click cannot spawn a second session from one cart.\n 'Idempotency-Key': attemptKey.current,\n },\n body: JSON.stringify({\n hostId,\n ...(email.trim() ? { email: email.trim() } : {}),\n ...(optIn ? { marketingOptIn: true } : {}),\n ...(coupon.trim() ? { couponCode: coupon.trim() } : {}),\n ...(giftCard.trim() ? { giftCardCode: giftCard.trim() } : {}),\n // A request, never an instruction: the server resolves the rates\n // for this country AND restricts the session's collectable\n // addresses to it, so declaring one cannot buy a cheaper zone's\n // rate than the address the shopper then enters (AGL-1721).\n ...(shipTo ? { shippingCountry: shipTo } : {}),\n ...(shipPostal.trim() ? { shippingPostalCode: shipPostal.trim() } : {}),\n // Which offers, never their price: the server asks the provider again.\n ...(extras.chosenIds.length ? { extras: extras.chosenIds } : {}),\n }),\n })\n const payload = await response.json().catch(() => ({}))\n // In-page payment (AGL-1944). Checked BEFORE the redirect branch: a\n // native session carries a client secret and no url, and if a server ever\n // sent both, navigating away would silently discard the form.\n //\n // `begin_checkout` is reported on BOTH paths, and from the same place, so\n // the GA4 funnel does not develop a hole the day the flag flips — a\n // storefront whose `begin_checkout` count halved would look like a\n // conversion collapse rather than a checkout that stopped redirecting.\n if (response.ok && payload?.clientSecret && payload?.publishableKey) {\n trackEvent(\n 'begin_checkout',\n buildBeginCheckoutParams({\n value: (cart?.subtotalCents ?? 0) / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n setNativeCheckout({\n clientSecret: String(payload.clientSecret),\n publishableKey: String(payload.publishableKey),\n wallets: CommerceModel.readStorefrontCheckoutWallets(payload.wallets),\n })\n setStatus('idle')\n return\n }\n if (response.ok && payload?.url) {\n // GA4 checkout funnel (AGL-1561, converted by AGL-1591). This used to\n // call `window.gtag` raw with `value`/`currency` only, so the same\n // event name arrived from this surface and from the console's plan\n // checkout in two different shapes — and this half carried no `items`,\n // which is the field GA4's ecommerce funnel is actually built on.\n //\n // The item ids are the PRODUCT ids `view_item` and `add_to_cart`\n // already send, so the three now join into one per-product funnel.\n // `value` is stated rather than derived because the cart subtotal is\n // authoritative after a coupon or gift card, which the line prices\n // below are not. No `billing_interval`: a storefront cart is not a\n // subscription.\n //\n // AWAITED before the redirect (AGL-1580). This surface registers no\n // transport, so delivery is a synchronous `window.gtag` call and the\n // await resolves immediately — a storefront checkout is not slowed by\n // one microtask. It is written this way anyway because the property\n // that makes it safe is invisible from here: the day this bundle grows\n // an async transport, or a host registers one for it, the bare call\n // would start losing the event on exactly the branch that navigates,\n // and nothing at this call site would look different.\n await trackEventBeforeNavigation(\n 'begin_checkout',\n buildBeginCheckoutParams({\n value: (cart?.subtotalCents ?? 0) / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n window.location.assign(payload.url)\n return\n }\n // A read-only lockdown answers 423 with the visitor pause copy\n // (AGL-1511). Rendering `payload.error` here would print the wire\n // token \"locked\" at a shopper, and the `severity=\"error\"` styling\n // would tell them their payment failed — the one thing this copy\n // exists to never say. So the refusal is parsed and shown as a calm\n // notice instead.\n const paused = Aglyn.parseLockdownRefusal(response.status, payload)\n if (paused) {\n setMessage(Aglyn.lockdownRefusalText(paused))\n setStatus('paused')\n return\n }\n // A store that never had payments configured (AGL-2019). The server's\n // own words are NOT rendered here even though they are safe today:\n // this is a visitor-facing surface, the 501 bodies differ between the\n // cart and buy-now doors, and one of them could grow a variable name\n // without anyone thinking about who reads it.\n // An offer the shopper ticked changed or went away (AGL-3635): show\n // what is offered now and let them decide again.\n if (payload?.extrasChanged) {\n extras.reload()\n setMessage(String(payload?.error ?? ''))\n setStatus('error')\n return\n }\n if (isPaymentsNotConfigured(response.status)) {\n setMessage(storefrontPaymentsNotConfiguredText())\n setStatus('unconfigured')\n return\n }\n // The merchant's rates differ by destination, so the server will not\n // price this cart until it knows one (AGL-1721). Reveal the field and\n // let the shopper answer; a store that never sends this never shows it.\n if (payload?.needsShippingCountry) {\n if (payload?.needsShippingPostalCode) setAskPostal(true)\n setShipCountries(\n (payload.shippingCountries as string[] | undefined)?.length\n ? (payload.shippingCountries as string[])\n : [...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES],\n )\n setMessage(String(payload?.error ?? ''))\n // An unserved destination is a real refusal and reads as one; being\n // asked the first time is not.\n setStatus(shipTo ? 'error' : 'ask')\n return\n }\n setMessage(String(payload?.error ?? ''))\n setStatus('error')\n } catch {\n setStatus('error')\n }\n // `cart` is a dependency because the payload above reads it: without it\n // the handler closes over whichever cart was current when it was created,\n // and a checkout started after a quantity change would report the OLD\n // subtotal and the OLD lines. The pre-AGL-1591 raw call had the same bug\n // in the `value` alone, where a wrong number is indistinguishable from a\n // right one.\n }, [hostId, cart, coupon, email, optIn, giftCard, shipTo, shipPostal, status, siteFetch, extras.chosenIds, extras.reload])\n\n if (!cart || cart.lines.length === 0) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ p: 2 }}>\n {emptyText || 'Your cart is empty.'}\n </Typography>\n )\n }\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, p: 2 }}>\n {cart.lines.map((line) => {\n // AGL-1726: resolve BEFORE the guard, never inside the `src`. A\n // stored value can be truthy and still resolve to nothing (a\n // malformed `media:` reference), and testing the raw string would\n // turn \"no image\" into an `<img>` with no `src` — a broken-image\n // icon where the placeholder belongs.\n const imageUrl = Aglyn.siteRelativeMediaSrc(line.imageUrl, { hostId })\n return (\n <Box\n key={`${line.productId}:${line.variantId ?? ''}`}\n sx={{ display: 'flex', gap: 1.5, alignItems: 'center' }}\n >\n {imageUrl ? (\n <Box\n component=\"img\"\n src={imageUrl}\n alt=\"\"\n sx={{\n width: 48,\n height: 48,\n objectFit: 'cover',\n borderRadius: 1,\n }}\n // Deferred (AGL-2486). A 48px cart-line thumbnail is the\n // clearest case of the set: it can never be the LCP, and a\n // cart is usually below the fold or inside a panel.\n {...Aglyn.DEFERRED_IMAGE_ATTRIBUTES}\n />\n ) : (\n <Box\n sx={{\n width: 48,\n height: 48,\n bgcolor: 'action.hover',\n borderRadius: 1,\n }}\n />\n )}\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {line.name}\n {line.variantLabel ? ` — ${line.variantLabel}` : ''}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {line.unavailable\n ? 'No longer available'\n : usd(line.unitAmountCents)}\n </Typography>\n </Box>\n <TextField\n value={quantityDrafts[lineKey(line)] ?? line.quantity}\n onChange={(event) =>\n setQuantityDrafts((drafts) => ({\n ...drafts,\n [lineKey(line)]: event.target.value,\n }))\n }\n onBlur={() => commitQuantity(line)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commitQuantity(line)\n }}\n size=\"small\"\n sx={{ width: 60 }}\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() =>\n void onMutate({\n action: 'remove',\n productId: line.productId,\n variantId: line.variantId,\n })\n }\n >\n {'✕'}\n </Button>\n </Box>\n )\n })}\n <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>\n <Typography variant=\"subtitle2\">{'Subtotal'}</Typography>\n <Typography variant=\"subtitle2\">{usd(cart.subtotalCents)}</Typography>\n </Box>\n <CartExtras\n offers={extras.offers}\n chosen={extras.chosen}\n onToggle={extras.toggle}\n formatCents={usd}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Shipping and taxes are calculated at checkout.'}\n </Typography>\n <TextField\n label=\"Email\"\n type=\"email\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n size=\"small\"\n helperText=\"For your receipt and order updates\"\n />\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n checked={optIn}\n onChange={(event) => setOptIn(event.target.checked)}\n />\n }\n label={\n <Typography variant=\"caption\">\n {'Email me news and offers'}\n </Typography>\n }\n />\n {showCoupon ? (\n <>\n <TextField\n label=\"Coupon code\"\n value={coupon}\n onChange={(event) => setCoupon(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Gift card\"\n value={giftCard}\n onChange={(event) => setGiftCard(event.target.value)}\n size=\"small\"\n placeholder=\"GC-…\"\n />\n </>\n ) : null}\n {shipCountries ? (\n <TextField\n select\n label=\"Ship to\"\n value={shipTo}\n onChange={(event) => setShipTo(event.target.value)}\n size=\"small\"\n helperText=\"Shipping rates depend on where this is going\"\n >\n {shipCountries.map((code) => (\n <MenuItem key={code} value={code}>\n {CommerceModel.CHECKOUT_SHIPPING_COUNTRY_NAMES[code] ?? code}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {askPostal ? (\n <TextField\n label=\"Postal code\"\n value={shipPostal}\n onChange={(event) => setShipPostal(event.target.value)}\n size=\"small\"\n helperText=\"Carrier rates depend on the postal code\"\n slotProps={{ htmlInput: { autoComplete: 'shipping postal-code', maxLength: 12 } }}\n />\n ) : null}\n {status === 'paused' || status === 'ask' || status === 'unconfigured' ? (\n <Alert severity=\"info\">{message}</Alert>\n ) : null}\n {status === 'error' ? (\n <Alert severity=\"error\">\n {message || 'Checkout is unavailable right now.'}\n </Alert>\n ) : null}\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n status === 'sending' ||\n cart.lines.every((line) => line.unavailable) ||\n // No payments on this deployment: every further click gets the same\n // 501, so the control latches off rather than inviting a retry that\n // cannot succeed (AGL-2019).\n status === 'unconfigured' ||\n // Asked but unanswered: the server would only refuse again.\n (shipCountries !== null && !shipTo) ||\n (askPostal && !shipPostal.trim())\n }\n onClick={handleCheckout}\n >\n {status === 'sending'\n ? // \"Redirecting\" stops being true the moment the form opens in\n // place (AGL-1944).\n nativeCheckout\n ? 'Opening…'\n : 'Redirecting…'\n : checkoutLabel || 'Checkout'}\n </Button>\n {nativeCheckout ? (\n <Suspense fallback={<StorefrontPaymentElementFallback />}>\n <StorefrontPaymentElement\n clientSecret={nativeCheckout.clientSecret}\n publishableKey={nativeCheckout.publishableKey}\n wallets={nativeCheckout.wallets}\n payLabel={checkoutLabel || 'Pay now'}\n defaultEmail={email}\n // An expired or unloadable session is replaced, never replayed:\n // the old attempt key would hand back the dead session.\n onRestart={() => {\n attemptKey.current = ''\n setNativeCheckout(null)\n void handleCheckout()\n }}\n // The session is left open on cancel, deliberately: it is what the\n // AGL-323 abandoned-cart recovery emails are built on, and expiring\n // it would be a write against the merchant's Stripe account made\n // from a browser.\n onCancel={() => setNativeCheckout(null)}\n />\n </Suspense>\n ) : null}\n </Box>\n )\n}\n\n/**\n * Cart block (AGL-293): 'button' renders a badge icon + slide-out\n * drawer for app bars; 'inline' renders the full cart for a cart page.\n * Lines live server-side (cookie cart); every mutation re-resolves\n * prices. Other blocks broadcast CART_UPDATED_EVENT to refresh badges.\n */\nconst Cart = forwardRef<HTMLDivElement, CartProps>((props, ref) => {\n const { variant, checkoutLabel, showCoupon, emptyText, ...rest } = props\n // Node styles ride the renderer-merged sx; recompose (stack.ts pattern).\n const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [props['sx']]\n const { hostId } = Aglyn.useSite()\n const siteFetch = Aglyn.useSiteFetch()\n const [cart, setCart] = useState<CartView | null>(null)\n const [open, setOpen] = useState(false)\n\n // Closes the merchant's ecommerce funnel (AGL-1641). Stripe returns a cart\n // checkout to the page it started on — this one — so the `purchase` that\n // `begin_checkout` above has never had a counterpart to is reported here.\n // No-ops on every ordinary render: the hook returns immediately unless the\n // URL carries `?order=success&session_id=…`.\n useStorefrontPurchaseEvent(hostId, siteFetch)\n\n const refresh = useCallback(async () => {\n if (!hostId) return\n try {\n const response = await fetch(\n `/api/commerce/cart?hostId=${encodeURIComponent(hostId)}`,\n )\n if (response.ok) setCart(await response.json())\n } catch {\n // Badge silently stays stale offline.\n }\n }, [hostId])\n\n useEffect(() => {\n void refresh()\n const handler = () => void refresh()\n window.addEventListener(CART_UPDATED_EVENT, handler)\n return () => window.removeEventListener(CART_UPDATED_EVENT, handler)\n }, [refresh])\n\n /**\n * Has THIS opening of the cart already been reported? A drawer that is\n * closed and reopened is a second view; a re-render, a badge refresh or a\n * quantity edit inside an already-open drawer is not.\n */\n const viewReported = useRef(false)\n\n /**\n * `view_cart` — the funnel step between `add_to_cart` and `begin_checkout`.\n *\n * Fired on the cart being SEEN, which is why it hangs off `open` rather off\n * mount: the button variant renders a badge on every page of a storefront,\n * and reporting a view there would have made \"opened the cart\" a synonym for\n * \"loaded a page\" and the checkout rate a fraction of pageviews.\n *\n * Deferred until the lines have actually arrived. The cart is fetched, so a\n * drawer opened while that request is in flight has nothing to describe yet\n * — reporting then would send an empty `items` and a zero `value` for a cart\n * that in fact had both. An empty cart never reports at all: there is no\n * view of nothing, and counting it would put every idle badge click into the\n * denominator of the checkout rate.\n */\n useEffect(() => {\n const onScreen = variant === 'inline' || open\n if (!onScreen) {\n viewReported.current = false\n return\n }\n if (viewReported.current || !cart || cart.lines.length === 0) return\n viewReported.current = true\n trackEvent(\n 'view_cart',\n buildViewCartParams({\n // The server's subtotal, so this and the `begin_checkout` the same\n // cart sends describe one cart at one size.\n value: cart.subtotalCents / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n }, [variant, open, cart])\n\n const mutate = useCallback(\n async (body: Record<string, unknown>) => {\n if (!hostId) return\n const response = await siteFetch('/api/commerce/cart', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId, ...body }),\n })\n if (response.ok) {\n setCart(await response.json())\n window.dispatchEvent(new Event(CART_UPDATED_EVENT))\n }\n },\n [hostId, siteFetch],\n )\n\n if (!hostId) {\n return (\n <Box\n ref={ref}\n {...rest}\n sx={[\n {\n p: variant === 'inline' ? 3 : 1,\n border: '1px dashed',\n borderColor: 'divider',\n borderRadius: 1,\n color: 'text.secondary',\n fontSize: 13,\n fontFamily: 'system-ui, sans-serif',\n display: 'inline-block',\n },\n ...nodeSx,\n ]}\n >\n {variant === 'inline' ? 'Cart — lines render here' : '🛒 Cart'}\n </Box>\n )\n }\n\n if (variant === 'inline') {\n return (\n <Box ref={ref} {...rest}>\n <CheckoutReturnNotice hostId={hostId} siteFetch={siteFetch} />\n <CartLines\n hostId={hostId}\n cart={cart}\n showCoupon={showCoupon}\n checkoutLabel={checkoutLabel}\n emptyText={emptyText}\n onMutate={mutate}\n />\n </Box>\n )\n }\n\n return (\n <Box ref={ref} {...rest} sx={[{ display: 'inline-flex' }, ...nodeSx]}>\n <CheckoutReturnNotice hostId={hostId} siteFetch={siteFetch} />\n <IconButton aria-label=\"Cart\" onClick={() => setOpen(true)}>\n <Badge badgeContent={cart?.count ?? 0} color=\"primary\">\n <SvgIcon>\n <path d={mdiCartOutline.path} />\n </SvgIcon>\n </Badge>\n </IconButton>\n <Drawer anchor=\"right\" open={open} onClose={() => setOpen(false)}>\n <Box sx={{ width: { xs: '85vw', sm: 380 } }}>\n <Typography variant=\"h6\" sx={{ p: 2, pb: 0 }}>\n {'Your cart'}\n </Typography>\n <CartLines\n hostId={hostId}\n cart={cart}\n showCoupon={showCoupon}\n checkoutLabel={checkoutLabel}\n emptyText={emptyText}\n onMutate={mutate}\n />\n </Box>\n </Drawer>\n </Box>\n )\n})\nCart.displayName = 'AglynCart'\n\nexport const schema: Aglyn.ComponentSchema<CartProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Cart',\n description:\n 'The shopping cart — a badge icon with a slide-out drawer, or the full cart page.',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'variant',\n label: 'Style',\n description: 'Icon-with-drawer for app bars, or the full inline cart.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'button', label: 'Icon + drawer' },\n { value: 'inline', label: 'Inline (cart page)' },\n ],\n },\n {\n name: 'checkoutLabel',\n label: 'Checkout label',\n description: 'Defaults to \"Checkout\".',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n // The PROP KEY stays `showCoupon` — it is persisted in every saved page\n // that uses this component, and renaming it would blank the control on\n // all of them. Only what the merchant reads changes.\n name: 'showCoupon',\n // ONE CONTROL, TWO FEATURES, AND IT ONLY NAMED ONE. This checkbox gates\n // the gift-card field as well as the coupon field, so a merchant who\n // wanted gift cards had no reason to look here — gift cards are only\n // redeemable in the cart, and this is the switch that shows the box.\n // A control named for one feature that also gates another is how a\n // shipped feature stays invisible.\n label: 'Show coupon and gift card fields',\n description:\n 'One checkbox for both. Coupon codes and gift cards are managed on ' +\n 'the Products page.',\n component: Aglyn.FieldComponentType.CHECKBOX,\n },\n {\n name: 'emptyText',\n label: 'Empty text',\n description: 'Copy when the cart is empty.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID, 'button'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Cart button',\n pluginId: BUNDLE_ID,\n description: 'Badge icon with a slide-out cart drawer',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'button' },\n },\n },\n {\n $id: generatePresetId(ID, 'inline'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Cart page',\n pluginId: BUNDLE_ID,\n description:\n 'Full cart with quantities, coupon, gift card, and checkout',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'inline', showCoupon: true },\n },\n },\n]\n\nexport default Cart\n"],"names":["Aglyn","buildBeginCheckoutParams","buildViewCartParams","trackEvent","trackEventBeforeNavigation","isPaymentsNotConfigured","storefrontPaymentsNotConfiguredText","CommerceModel","mdiCartOutline","Alert","Badge","Box","Button","Checkbox","Drawer","FormControlLabel","IconButton","MenuItem","SvgIcon","TextField","Typography","Suspense","forwardRef","lazy","useCallback","useEffect","useMemo","useRef","useState","StorefrontPaymentElementFallback","CheckoutReturnNotice","CartExtras","useCartExtras","StorefrontPaymentElement","then","module","default","BUNDLE_ID","generatePresetId","useStorefrontPurchaseEvent","ID","CART_UPDATED_EVENT","usd","cents","toFixed","cartAnalyticsItems","cart","lines","map","line","item_id","productId","item_name","name","price","unitAmountCents","quantity","CartLines","props","hostId","showCoupon","checkoutLabel","emptyText","onMutate","siteFetch","useSiteFetch","coupon","setCoupon","email","setEmail","optIn","setOptIn","giftCard","setGiftCard","shipTo","setShipTo","shipCountries","setShipCountries","shipPostal","setShipPostal","askPostal","setAskPostal","status","setStatus","message","setMessage","nativeCheckout","setNativeCheckout","quantityDrafts","setQuantityDrafts","lineKey","variantId","commitQuantity","key","draft","undefined","settle","drafts","_settled","rest","trim","parsed","Math","round","Number","isFinite","max","action","finally","attemptKey","cartSignature","JSON","stringify","extras","extrasSignature","chosenIds","join","current","handleCheckout","globalThis","crypto","randomUUID","Date","now","random","toString","slice","response","method","headers","body","marketingOptIn","couponCode","giftCardCode","shippingCountry","shippingPostalCode","length","payload","json","catch","ok","clientSecret","publishableKey","value","subtotalCents","items","String","wallets","readStorefrontCheckoutWallets","url","window","location","assign","paused","parseLockdownRefusal","lockdownRefusalText","extrasChanged","reload","error","needsShippingCountry","needsShippingPostalCode","shippingCountries","CHECKOUT_SHIPPING_COUNTRIES","variant","color","sx","p","display","flexDirection","gap","imageUrl","siteRelativeMediaSrc","alignItems","component","src","alt","width","height","objectFit","borderRadius","DEFERRED_IMAGE_ATTRIBUTES","bgcolor","flex","minWidth","noWrap","variantLabel","unavailable","onChange","event","target","onBlur","onKeyDown","size","slotProps","htmlInput","inputMode","onClick","justifyContent","offers","chosen","onToggle","toggle","formatCents","label","type","helperText","control","checked","placeholder","select","code","CHECKOUT_SHIPPING_COUNTRY_NAMES","autoComplete","maxLength","severity","disabled","every","fallback","payLabel","defaultEmail","onRestart","onCancel","Cart","ref","nodeSx","Array","isArray","useSite","setCart","open","setOpen","refresh","fetch","encodeURIComponent","handler","addEventListener","removeEventListener","viewReported","onScreen","mutate","dispatchEvent","Event","border","borderColor","fontSize","fontFamily","aria-label","badgeContent","count","path","d","anchor","onClose","xs","sm","pb","displayName","schema","$id","pluginId","description","category","ComponentCategory","COMMERCE","icon","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","FieldComponentType","SELECT","options","TEXT_FIELD","CHECKBOX","presets","NodeType","PRESET","data","componentId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/cart.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\nimport * as Aglyn from '@aglyn/aglyn'\nimport {\n buildBeginCheckoutParams,\n buildViewCartParams,\n trackEvent,\n trackEventBeforeNavigation,\n type AnalyticsItem,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { isPaymentsNotConfigured } from '@aglyn/aglyn/app-utils/payments-configured'\nimport { storefrontPaymentsNotConfiguredText } from '../constants/storefront-payments'\nimport * as CommerceModel from '../model'\nimport { mdiCartOutline } from '@aglyn/shared-data-mdi'\nimport Alert from '@mui/material/Alert'\nimport Badge from '@mui/material/Badge'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Checkbox from '@mui/material/Checkbox'\nimport Drawer from '@mui/material/Drawer'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport IconButton from '@mui/material/IconButton'\nimport MenuItem from '@mui/material/MenuItem'\nimport SvgIcon from '@mui/material/SvgIcon'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport {\n Suspense,\n forwardRef,\n lazy,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { StorefrontPaymentElementFallback } from './storefront-payment-element-fallback'\nimport { CheckoutReturnNotice } from './checkout-return-notice'\nimport { CartExtras, useCartExtras } from './cart-extras'\nimport { CartFulfillmentChoice, useCartFulfillment } from './cart-fulfillment'\n\n/**\n * The Payment Element (AGL-1944), lazily. Stripe.js and its React wrapper are\n * a large dependency and the flag is OFF, so a static import would ship the\n * whole SDK in the bundle of every page carrying a cart — which is most pages\n * on a storefront — to serve a path no shopper currently reaches.\n */\nconst StorefrontPaymentElement = lazy(() =>\n import('./storefront-payment-element').then((module) => ({\n default: module.StorefrontPaymentElement,\n })),\n)\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { generatePresetId } from '../utils/generate-preset-id'\nimport { useStorefrontPurchaseEvent } from '../utils/use-storefront-purchase-event'\n\n// Component ids are persisted in screen documents; never rename.\nexport const ID: Aglyn.ComponentId = 'cart'\n\n/** Blocks dispatch this after mutating the cart so badges refresh. */\nexport const CART_UPDATED_EVENT = 'aglyn:cart-updated'\n\nexport interface CartProps {\n /** 'button' = app-bar icon + drawer; 'inline' = full cart in place. */\n variant?: 'button' | 'inline'\n checkoutLabel?: string\n /** Show the coupon-code field above checkout. */\n showCoupon?: boolean\n emptyText?: string\n}\n\ninterface CartLineView {\n productId: string\n variantId?: string\n quantity: number\n name: string\n variantLabel?: string\n unitAmountCents: number\n imageUrl?: string\n unavailable?: boolean\n}\n\ninterface CartView {\n lines: CartLineView[]\n count: number\n subtotalCents: number\n}\n\nconst usd = (cents: number) => `$${(cents / 100).toFixed(2)}`\n\n/**\n * The cart's lines as GA4 `items`.\n *\n * One mapping for every event this file sends — `view_cart` and both\n * `begin_checkout` branches — because the `item_id` is what joins them into a\n * single per-product funnel with the `view_item` and `add_to_cart` the product\n * blocks send. Three hand-written copies of the same map are three chances for\n * one step to start reporting a variant id, or a name, or a different price\n * basis, and a funnel whose steps disagree about the product silently reports\n * a drop that never happened.\n */\nfunction cartAnalyticsItems(cart: CartView | null): AnalyticsItem[] {\n return (cart?.lines ?? []).map((line) => ({\n item_id: line.productId,\n item_name: line.name,\n price: line.unitAmountCents / 100,\n quantity: line.quantity,\n }))\n}\n\nfunction CartLines(props: {\n hostId: string\n cart: CartView | null\n showCoupon?: boolean\n checkoutLabel?: string\n emptyText?: string\n onMutate: (body: Record<string, unknown>) => Promise<void>\n}) {\n const { hostId, cart, showCoupon, checkoutLabel, emptyText, onMutate } =\n props\n const siteFetch = Aglyn.useSiteFetch()\n const [coupon, setCoupon] = useState('')\n const [email, setEmail] = useState('')\n const [optIn, setOptIn] = useState(false)\n const [giftCard, setGiftCard] = useState('')\n // A rewards or referral code (AGL-3640), asked only where the store takes one.\n const [creditCode, setCreditCode] = useState('')\n // Where the parcel is going (AGL-1721). Asked ONLY when the server says it\n // cannot price shipping without it — a merchant with one zone, one\n // rest-of-world zone, or no shipping at all never sees this field, which is\n // the common configuration. `null` is \"not asked\", so the field appearing is\n // itself the server's answer rather than a guess made here.\n const [shipTo, setShipTo] = useState('')\n const [shipCountries, setShipCountries] = useState<string[] | null>(null)\n // Live carrier rates price by postal code (AGL-3612): asked only when the\n // store prices that way and the server says so.\n const [shipPostal, setShipPostal] = useState('')\n const [askPostal, setAskPostal] = useState(false)\n // `paused` is its own state, not an `error` with gentler words (AGL-1511):\n // the two need different severities, and a shopper told in red that\n // checkout failed does not read the sentence explaining it did not. `ask` is\n // the same argument again: being asked for a destination is not a failure.\n // `unconfigured` is the third instance (AGL-2019): a store with no Stripe key\n // answers 501, and before this that fell through to the error tail below and\n // rendered RED. It is also the only one of the five that is TERMINAL — the\n // others can succeed on a retry, this one cannot until the operator acts, so\n // it latches the buy control off instead of inviting another click.\n const [status, setStatus] = useState<\n 'idle' | 'sending' | 'error' | 'paused' | 'ask' | 'unconfigured'\n >('idle')\n const [message, setMessage] = useState('')\n /**\n * The in-page checkout session (AGL-1944). Null unless the server chose\n * native mode, which needs both the release flag and a publishable key.\n */\n const [nativeCheckout, setNativeCheckout] = useState<{\n clientSecret: string\n publishableKey: string\n /** The wallets the merchant hid (AGL-3629). */\n wallets?: CommerceModel.StorefrontCheckoutWallets\n } | null>(null)\n /**\n * In-progress quantity edits, keyed by line, as the raw field text\n * (AGL-1772). The field used to POST /api/commerce/cart on every\n * keystroke — typing \"100\" was three Firestore writes, and clearing the\n * field to retype passed through `\"\"` → 0, which is the REMOVE path, so a\n * select-all-and-retype could delete the line mid-edit (and the response\n * replacing `cart` state then fought the input).\n *\n * The repo convention for quantity inputs is local state committed on an\n * explicit settle — the PDP's Qty field (product-detail.tsx) holds\n * `useState` and sends nothing until the buy click, and besigner\n * attributes commit on blur. So: keystrokes only edit the draft; blur or\n * Enter commits ONE write; an empty or unparsable draft is a pending\n * state that reverts to the server's quantity, never a 0-as-remove. A\n * genuine remove still works both ways — the ✕ button, and typing an\n * actual 0 then leaving the field.\n */\n const [quantityDrafts, setQuantityDrafts] = useState<Record<string, string>>(\n {},\n )\n const lineKey = (line: CartLineView) =>\n `${line.productId}:${line.variantId ?? ''}`\n const commitQuantity = (line: CartLineView) => {\n const key = lineKey(line)\n const draft = quantityDrafts[key]\n if (draft === undefined) return\n // Drops the draft, but only if it is still THIS one — a keystroke that\n // lands while the write is in flight starts a new edit, and clearing it\n // here would erase what the shopper is typing.\n const settle = () =>\n setQuantityDrafts((drafts) => {\n if (drafts[key] !== draft) return drafts\n const { [key]: _settled, ...rest } = drafts\n return rest\n })\n // `Number('')` is 0 — exactly the misreading that turned a cleared\n // field into a remove. Empty means \"no answer\": show the server's\n // quantity again and write nothing. NaN (letters) reverts the same way.\n if (draft.trim() === '') return settle()\n const parsed = Math.round(Number(draft))\n if (!Number.isFinite(parsed)) return settle()\n const quantity = Math.max(0, parsed)\n // A settled value equal to the server's is not an edit.\n if (quantity === line.quantity) return settle()\n // The draft keeps rendering until the response lands, so the field does\n // not flash the superseded quantity during the round-trip; the server's\n // answer (via the replaced `cart`) takes over when it arrives.\n void onMutate({\n action: 'set',\n productId: line.productId,\n variantId: line.variantId,\n quantity,\n }).finally(settle)\n }\n\n /**\n * Idempotency key for ONE checkout attempt (AGL-1697).\n *\n * Minted lazily on the first checkout click, retired whenever the attempt\n * changes shape — different lines, codes, email or destination are a\n * different checkout. Keyed off a CONTENT signature of the lines rather\n * than the `cart` object, whose identity changes on every refetch: retiring\n * on identity would hand a genuine retry a fresh key, which is exactly the\n * double-session this exists to prevent.\n */\n const attemptKey = useRef('')\n const cartSignature = useMemo(\n () =>\n JSON.stringify(\n (cart?.lines ?? []).map((line) => [\n line.productId,\n line.variantId ?? '',\n line.quantity,\n ]),\n ),\n [cart],\n )\n // Optional lines another plugin offers (AGL-3635), asked while the cart is shown.\n const extras = useCartExtras(hostId, cartSignature)\n const extrasSignature = extras.chosenIds.join(',')\n // Shipped, picked up, or the store's own delivery (AGL-3624).\n const fulfillment = useCartFulfillment(hostId, cartSignature)\n useEffect(() => {\n attemptKey.current = ''\n }, [cartSignature, email, coupon, giftCard, creditCode, shipTo, shipPostal, extrasSignature, fulfillment.signature])\n\n const handleCheckout = useCallback(async () => {\n if (status === 'sending') return\n setStatus('sending')\n setMessage('')\n if (!attemptKey.current) {\n attemptKey.current =\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n try {\n const response = await siteFetch('/api/commerce/cart-checkout', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // Stable across a retry of THIS attempt (AGL-1697), so a\n // double-click cannot spawn a second session from one cart.\n 'Idempotency-Key': attemptKey.current,\n },\n body: JSON.stringify({\n hostId,\n ...(email.trim() ? { email: email.trim() } : {}),\n ...(optIn ? { marketingOptIn: true } : {}),\n ...(coupon.trim() ? { couponCode: coupon.trim() } : {}),\n ...(giftCard.trim() ? { giftCardCode: giftCard.trim() } : {}),\n ...(creditCode.trim() && extras.credits.length ? { creditCode: creditCode.trim() } : {}),\n // A request, never an instruction: the server resolves the rates\n // for this country AND restricts the session's collectable\n // addresses to it, so declaring one cannot buy a cheaper zone's\n // rate than the address the shopper then enters (AGL-1721).\n ...(shipTo && !fulfillment.request ? { shippingCountry: shipTo } : {}),\n ...(shipPostal.trim() && !fulfillment.request ? { shippingPostalCode: shipPostal.trim() } : {}),\n // Which offers, never their price: the server asks the provider again.\n ...(extras.chosenIds.length ? { extras: extras.chosenIds } : {}),\n // Where and when, never the fee: the server decides it again.\n ...(fulfillment.request ? { fulfillment: fulfillment.request } : {}),\n }),\n })\n const payload = await response.json().catch(() => ({}))\n // In-page payment (AGL-1944). Checked BEFORE the redirect branch: a\n // native session carries a client secret and no url, and if a server ever\n // sent both, navigating away would silently discard the form.\n //\n // `begin_checkout` is reported on BOTH paths, and from the same place, so\n // the GA4 funnel does not develop a hole the day the flag flips — a\n // storefront whose `begin_checkout` count halved would look like a\n // conversion collapse rather than a checkout that stopped redirecting.\n if (response.ok && payload?.clientSecret && payload?.publishableKey) {\n trackEvent(\n 'begin_checkout',\n buildBeginCheckoutParams({\n value: (cart?.subtotalCents ?? 0) / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n setNativeCheckout({\n clientSecret: String(payload.clientSecret),\n publishableKey: String(payload.publishableKey),\n wallets: CommerceModel.readStorefrontCheckoutWallets(payload.wallets),\n })\n setStatus('idle')\n return\n }\n if (response.ok && payload?.url) {\n // GA4 checkout funnel (AGL-1561, converted by AGL-1591). This used to\n // call `window.gtag` raw with `value`/`currency` only, so the same\n // event name arrived from this surface and from the console's plan\n // checkout in two different shapes — and this half carried no `items`,\n // which is the field GA4's ecommerce funnel is actually built on.\n //\n // The item ids are the PRODUCT ids `view_item` and `add_to_cart`\n // already send, so the three now join into one per-product funnel.\n // `value` is stated rather than derived because the cart subtotal is\n // authoritative after a coupon or gift card, which the line prices\n // below are not. No `billing_interval`: a storefront cart is not a\n // subscription.\n //\n // AWAITED before the redirect (AGL-1580). This surface registers no\n // transport, so delivery is a synchronous `window.gtag` call and the\n // await resolves immediately — a storefront checkout is not slowed by\n // one microtask. It is written this way anyway because the property\n // that makes it safe is invisible from here: the day this bundle grows\n // an async transport, or a host registers one for it, the bare call\n // would start losing the event on exactly the branch that navigates,\n // and nothing at this call site would look different.\n await trackEventBeforeNavigation(\n 'begin_checkout',\n buildBeginCheckoutParams({\n value: (cart?.subtotalCents ?? 0) / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n window.location.assign(payload.url)\n return\n }\n // A read-only lockdown answers 423 with the visitor pause copy\n // (AGL-1511). Rendering `payload.error` here would print the wire\n // token \"locked\" at a shopper, and the `severity=\"error\"` styling\n // would tell them their payment failed — the one thing this copy\n // exists to never say. So the refusal is parsed and shown as a calm\n // notice instead.\n const paused = Aglyn.parseLockdownRefusal(response.status, payload)\n if (paused) {\n setMessage(Aglyn.lockdownRefusalText(paused))\n setStatus('paused')\n return\n }\n // A store that never had payments configured (AGL-2019). The server's\n // own words are NOT rendered here even though they are safe today:\n // this is a visitor-facing surface, the 501 bodies differ between the\n // cart and buy-now doors, and one of them could grow a variable name\n // without anyone thinking about who reads it.\n // An offer the shopper ticked changed or went away (AGL-3635): show\n // what is offered now and let them decide again.\n if (payload?.extrasChanged) {\n extras.reload()\n setMessage(String(payload?.error ?? ''))\n setStatus('error')\n return\n }\n // The pickup location or delivery time went away while the cart was\n // open (AGL-3624): ask again and let the shopper choose.\n if (payload?.fulfillmentChanged) {\n fulfillment.reload()\n setMessage(String(payload?.error ?? ''))\n setStatus('error')\n return\n }\n if (isPaymentsNotConfigured(response.status)) {\n setMessage(storefrontPaymentsNotConfiguredText())\n setStatus('unconfigured')\n return\n }\n // The merchant's rates differ by destination, so the server will not\n // price this cart until it knows one (AGL-1721). Reveal the field and\n // let the shopper answer; a store that never sends this never shows it.\n if (payload?.needsShippingCountry) {\n if (payload?.needsShippingPostalCode) setAskPostal(true)\n setShipCountries(\n (payload.shippingCountries as string[] | undefined)?.length\n ? (payload.shippingCountries as string[])\n : [...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES],\n )\n setMessage(String(payload?.error ?? ''))\n // An unserved destination is a real refusal and reads as one; being\n // asked the first time is not.\n setStatus(shipTo ? 'error' : 'ask')\n return\n }\n setMessage(String(payload?.error ?? ''))\n setStatus('error')\n } catch {\n setStatus('error')\n }\n // `cart` is a dependency because the payload above reads it: without it\n // the handler closes over whichever cart was current when it was created,\n // and a checkout started after a quantity change would report the OLD\n // subtotal and the OLD lines. The pre-AGL-1591 raw call had the same bug\n // in the `value` alone, where a wrong number is indistinguishable from a\n // right one.\n }, [hostId, cart, coupon, email, optIn, giftCard, creditCode, shipTo, shipPostal, status, siteFetch, extras.chosenIds, extras.reload, extras.credits.length, fulfillment.request, fulfillment.reload])\n\n if (!cart || cart.lines.length === 0) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ p: 2 }}>\n {emptyText || 'Your cart is empty.'}\n </Typography>\n )\n }\n return (\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, p: 2 }}>\n {cart.lines.map((line) => {\n // AGL-1726: resolve BEFORE the guard, never inside the `src`. A\n // stored value can be truthy and still resolve to nothing (a\n // malformed `media:` reference), and testing the raw string would\n // turn \"no image\" into an `<img>` with no `src` — a broken-image\n // icon where the placeholder belongs.\n const imageUrl = Aglyn.siteRelativeMediaSrc(line.imageUrl, { hostId })\n return (\n <Box\n key={`${line.productId}:${line.variantId ?? ''}`}\n sx={{ display: 'flex', gap: 1.5, alignItems: 'center' }}\n >\n {imageUrl ? (\n <Box\n component=\"img\"\n src={imageUrl}\n alt=\"\"\n sx={{\n width: 48,\n height: 48,\n objectFit: 'cover',\n borderRadius: 1,\n }}\n // Deferred (AGL-2486). A 48px cart-line thumbnail is the\n // clearest case of the set: it can never be the LCP, and a\n // cart is usually below the fold or inside a panel.\n {...Aglyn.DEFERRED_IMAGE_ATTRIBUTES}\n />\n ) : (\n <Box\n sx={{\n width: 48,\n height: 48,\n bgcolor: 'action.hover',\n borderRadius: 1,\n }}\n />\n )}\n <Box sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {line.name}\n {line.variantLabel ? ` — ${line.variantLabel}` : ''}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {line.unavailable\n ? 'No longer available'\n : usd(line.unitAmountCents)}\n </Typography>\n </Box>\n <TextField\n value={quantityDrafts[lineKey(line)] ?? line.quantity}\n onChange={(event) =>\n setQuantityDrafts((drafts) => ({\n ...drafts,\n [lineKey(line)]: event.target.value,\n }))\n }\n onBlur={() => commitQuantity(line)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commitQuantity(line)\n }}\n size=\"small\"\n sx={{ width: 60 }}\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() =>\n void onMutate({\n action: 'remove',\n productId: line.productId,\n variantId: line.variantId,\n })\n }\n >\n {'✕'}\n </Button>\n </Box>\n )\n })}\n <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>\n <Typography variant=\"subtitle2\">{'Subtotal'}</Typography>\n <Typography variant=\"subtitle2\">{usd(cart.subtotalCents)}</Typography>\n </Box>\n <CartExtras\n offers={extras.offers}\n chosen={extras.chosen}\n onToggle={extras.toggle}\n formatCents={usd}\n />\n <CartFulfillmentChoice state={fulfillment} formatCents={usd} />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {fulfillment.method === 'shipping'\n ? 'Shipping and taxes are calculated at checkout.'\n : 'Taxes are calculated at checkout.'}\n </Typography>\n <TextField\n label=\"Email\"\n type=\"email\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n size=\"small\"\n helperText=\"For your receipt and order updates\"\n />\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n checked={optIn}\n onChange={(event) => setOptIn(event.target.checked)}\n />\n }\n label={\n <Typography variant=\"caption\">\n {'Email me news and offers'}\n </Typography>\n }\n />\n {showCoupon ? (\n <>\n <TextField\n label=\"Coupon code\"\n value={coupon}\n onChange={(event) => setCoupon(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Gift card\"\n value={giftCard}\n onChange={(event) => setGiftCard(event.target.value)}\n size=\"small\"\n placeholder=\"GC-…\"\n />\n </>\n ) : null}\n {extras.credits.length ? (\n // Drawn wherever the store takes a code, coupon field or not: a\n // member was emailed theirs and comes here to spend it (AGL-3640).\n <TextField\n label={`${extras.credits[0].label} code`}\n value={creditCode}\n onChange={(event) => setCreditCode(event.target.value)}\n size=\"small\"\n slotProps={{ htmlInput: { 'data-testid': 'cart-credit-code' } }}\n />\n ) : null}\n {shipCountries && fulfillment.method === 'shipping' ? (\n <TextField\n select\n label=\"Ship to\"\n value={shipTo}\n onChange={(event) => setShipTo(event.target.value)}\n size=\"small\"\n helperText=\"Shipping rates depend on where this is going\"\n >\n {shipCountries.map((code) => (\n <MenuItem key={code} value={code}>\n {CommerceModel.CHECKOUT_SHIPPING_COUNTRY_NAMES[code] ?? code}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {askPostal && fulfillment.method === 'shipping' ? (\n <TextField\n label=\"Postal code\"\n value={shipPostal}\n onChange={(event) => setShipPostal(event.target.value)}\n size=\"small\"\n helperText=\"Carrier rates depend on the postal code\"\n slotProps={{ htmlInput: { autoComplete: 'shipping postal-code', maxLength: 12 } }}\n />\n ) : null}\n {status === 'paused' || status === 'ask' || status === 'unconfigured' ? (\n <Alert severity=\"info\">{message}</Alert>\n ) : null}\n {status === 'error' ? (\n <Alert severity=\"error\">\n {message || 'Checkout is unavailable right now.'}\n </Alert>\n ) : null}\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n status === 'sending' ||\n cart.lines.every((line) => line.unavailable) ||\n // No payments on this deployment: every further click gets the same\n // 501, so the control latches off rather than inviting a retry that\n // cannot succeed (AGL-2019).\n status === 'unconfigured' ||\n // Asked but unanswered: the server would only refuse again.\n (fulfillment.method === 'shipping' && shipCountries !== null && !shipTo) ||\n (fulfillment.method === 'shipping' && askPostal && !shipPostal.trim()) ||\n // Pickup needs a location, delivery a zone and a time (AGL-3624).\n !fulfillment.ready\n }\n onClick={handleCheckout}\n >\n {status === 'sending'\n ? // \"Redirecting\" stops being true the moment the form opens in\n // place (AGL-1944).\n nativeCheckout\n ? 'Opening…'\n : 'Redirecting…'\n : checkoutLabel || 'Checkout'}\n </Button>\n {nativeCheckout ? (\n <Suspense fallback={<StorefrontPaymentElementFallback />}>\n <StorefrontPaymentElement\n clientSecret={nativeCheckout.clientSecret}\n publishableKey={nativeCheckout.publishableKey}\n wallets={nativeCheckout.wallets}\n payLabel={checkoutLabel || 'Pay now'}\n defaultEmail={email}\n // An expired or unloadable session is replaced, never replayed:\n // the old attempt key would hand back the dead session.\n onRestart={() => {\n attemptKey.current = ''\n setNativeCheckout(null)\n void handleCheckout()\n }}\n // The session is left open on cancel, deliberately: it is what the\n // AGL-323 abandoned-cart recovery emails are built on, and expiring\n // it would be a write against the merchant's Stripe account made\n // from a browser.\n onCancel={() => setNativeCheckout(null)}\n />\n </Suspense>\n ) : null}\n </Box>\n )\n}\n\n/**\n * Cart block (AGL-293): 'button' renders a badge icon + slide-out\n * drawer for app bars; 'inline' renders the full cart for a cart page.\n * Lines live server-side (cookie cart); every mutation re-resolves\n * prices. Other blocks broadcast CART_UPDATED_EVENT to refresh badges.\n */\nconst Cart = forwardRef<HTMLDivElement, CartProps>((props, ref) => {\n const { variant, checkoutLabel, showCoupon, emptyText, ...rest } = props\n // Node styles ride the renderer-merged sx; recompose (stack.ts pattern).\n const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [props['sx']]\n const { hostId } = Aglyn.useSite()\n const siteFetch = Aglyn.useSiteFetch()\n const [cart, setCart] = useState<CartView | null>(null)\n const [open, setOpen] = useState(false)\n\n // Closes the merchant's ecommerce funnel (AGL-1641). Stripe returns a cart\n // checkout to the page it started on — this one — so the `purchase` that\n // `begin_checkout` above has never had a counterpart to is reported here.\n // No-ops on every ordinary render: the hook returns immediately unless the\n // URL carries `?order=success&session_id=…`.\n useStorefrontPurchaseEvent(hostId, siteFetch)\n\n const refresh = useCallback(async () => {\n if (!hostId) return\n try {\n const response = await fetch(\n `/api/commerce/cart?hostId=${encodeURIComponent(hostId)}`,\n )\n if (response.ok) setCart(await response.json())\n } catch {\n // Badge silently stays stale offline.\n }\n }, [hostId])\n\n useEffect(() => {\n void refresh()\n const handler = () => void refresh()\n window.addEventListener(CART_UPDATED_EVENT, handler)\n return () => window.removeEventListener(CART_UPDATED_EVENT, handler)\n }, [refresh])\n\n /**\n * Has THIS opening of the cart already been reported? A drawer that is\n * closed and reopened is a second view; a re-render, a badge refresh or a\n * quantity edit inside an already-open drawer is not.\n */\n const viewReported = useRef(false)\n\n /**\n * `view_cart` — the funnel step between `add_to_cart` and `begin_checkout`.\n *\n * Fired on the cart being SEEN, which is why it hangs off `open` rather off\n * mount: the button variant renders a badge on every page of a storefront,\n * and reporting a view there would have made \"opened the cart\" a synonym for\n * \"loaded a page\" and the checkout rate a fraction of pageviews.\n *\n * Deferred until the lines have actually arrived. The cart is fetched, so a\n * drawer opened while that request is in flight has nothing to describe yet\n * — reporting then would send an empty `items` and a zero `value` for a cart\n * that in fact had both. An empty cart never reports at all: there is no\n * view of nothing, and counting it would put every idle badge click into the\n * denominator of the checkout rate.\n */\n useEffect(() => {\n const onScreen = variant === 'inline' || open\n if (!onScreen) {\n viewReported.current = false\n return\n }\n if (viewReported.current || !cart || cart.lines.length === 0) return\n viewReported.current = true\n trackEvent(\n 'view_cart',\n buildViewCartParams({\n // The server's subtotal, so this and the `begin_checkout` the same\n // cart sends describe one cart at one size.\n value: cart.subtotalCents / 100,\n items: cartAnalyticsItems(cart),\n }),\n )\n }, [variant, open, cart])\n\n const mutate = useCallback(\n async (body: Record<string, unknown>) => {\n if (!hostId) return\n const response = await siteFetch('/api/commerce/cart', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId, ...body }),\n })\n if (response.ok) {\n setCart(await response.json())\n window.dispatchEvent(new Event(CART_UPDATED_EVENT))\n }\n },\n [hostId, siteFetch],\n )\n\n if (!hostId) {\n return (\n <Box\n ref={ref}\n {...rest}\n sx={[\n {\n p: variant === 'inline' ? 3 : 1,\n border: '1px dashed',\n borderColor: 'divider',\n borderRadius: 1,\n color: 'text.secondary',\n fontSize: 13,\n fontFamily: 'system-ui, sans-serif',\n display: 'inline-block',\n },\n ...nodeSx,\n ]}\n >\n {variant === 'inline' ? 'Cart — lines render here' : '🛒 Cart'}\n </Box>\n )\n }\n\n if (variant === 'inline') {\n return (\n <Box ref={ref} {...rest}>\n <CheckoutReturnNotice hostId={hostId} siteFetch={siteFetch} />\n <CartLines\n hostId={hostId}\n cart={cart}\n showCoupon={showCoupon}\n checkoutLabel={checkoutLabel}\n emptyText={emptyText}\n onMutate={mutate}\n />\n </Box>\n )\n }\n\n return (\n <Box ref={ref} {...rest} sx={[{ display: 'inline-flex' }, ...nodeSx]}>\n <CheckoutReturnNotice hostId={hostId} siteFetch={siteFetch} />\n <IconButton aria-label=\"Cart\" onClick={() => setOpen(true)}>\n <Badge badgeContent={cart?.count ?? 0} color=\"primary\">\n <SvgIcon>\n <path d={mdiCartOutline.path} />\n </SvgIcon>\n </Badge>\n </IconButton>\n <Drawer anchor=\"right\" open={open} onClose={() => setOpen(false)}>\n <Box sx={{ width: { xs: '85vw', sm: 380 } }}>\n <Typography variant=\"h6\" sx={{ p: 2, pb: 0 }}>\n {'Your cart'}\n </Typography>\n <CartLines\n hostId={hostId}\n cart={cart}\n showCoupon={showCoupon}\n checkoutLabel={checkoutLabel}\n emptyText={emptyText}\n onMutate={mutate}\n />\n </Box>\n </Drawer>\n </Box>\n )\n})\nCart.displayName = 'AglynCart'\n\nexport const schema: Aglyn.ComponentSchema<CartProps> = {\n $id: ID,\n pluginId: BUNDLE_ID,\n displayName: 'Cart',\n description:\n 'The shopping cart — a badge icon with a slide-out drawer, or the full cart page.',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'variant',\n label: 'Style',\n description: 'Icon-with-drawer for app bars, or the full inline cart.',\n component: Aglyn.FieldComponentType.SELECT,\n options: [\n { value: 'button', label: 'Icon + drawer' },\n { value: 'inline', label: 'Inline (cart page)' },\n ],\n },\n {\n name: 'checkoutLabel',\n label: 'Checkout label',\n description: 'Defaults to \"Checkout\".',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n {\n // The PROP KEY stays `showCoupon` — it is persisted in every saved page\n // that uses this component, and renaming it would blank the control on\n // all of them. Only what the merchant reads changes.\n name: 'showCoupon',\n // ONE CONTROL, TWO FEATURES, AND IT ONLY NAMED ONE. This checkbox gates\n // the gift-card field as well as the coupon field, so a merchant who\n // wanted gift cards had no reason to look here — gift cards are only\n // redeemable in the cart, and this is the switch that shows the box.\n // A control named for one feature that also gates another is how a\n // shipped feature stays invisible.\n label: 'Show coupon and gift card fields',\n description:\n 'One checkbox for both. Coupon codes and gift cards are managed on ' +\n 'the Products page.',\n component: Aglyn.FieldComponentType.CHECKBOX,\n },\n {\n name: 'emptyText',\n label: 'Empty text',\n description: 'Copy when the cart is empty.',\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n}\n\nexport const presets: Aglyn.PresetSchema[] = [\n {\n $id: generatePresetId(ID, 'button'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Cart button',\n pluginId: BUNDLE_ID,\n description: 'Badge icon with a slide-out cart drawer',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'button' },\n },\n },\n {\n $id: generatePresetId(ID, 'inline'),\n type: Aglyn.NodeType.PRESET,\n displayName: 'Cart page',\n pluginId: BUNDLE_ID,\n description:\n 'Full cart with quantities, coupon, gift card, and checkout',\n category: Aglyn.ComponentCategory.COMMERCE,\n icon: { path: mdiCartOutline.path, sx: { color: '#2e7d32' } },\n data: {\n $id: null,\n componentId: ID,\n pluginId: BUNDLE_ID,\n props: { variant: 'inline', showCoupon: true },\n },\n },\n]\n\nexport default Cart\n"],"names":["Aglyn","buildBeginCheckoutParams","buildViewCartParams","trackEvent","trackEventBeforeNavigation","isPaymentsNotConfigured","storefrontPaymentsNotConfiguredText","CommerceModel","mdiCartOutline","Alert","Badge","Box","Button","Checkbox","Drawer","FormControlLabel","IconButton","MenuItem","SvgIcon","TextField","Typography","Suspense","forwardRef","lazy","useCallback","useEffect","useMemo","useRef","useState","StorefrontPaymentElementFallback","CheckoutReturnNotice","CartExtras","useCartExtras","CartFulfillmentChoice","useCartFulfillment","StorefrontPaymentElement","then","module","default","BUNDLE_ID","generatePresetId","useStorefrontPurchaseEvent","ID","CART_UPDATED_EVENT","usd","cents","toFixed","cartAnalyticsItems","cart","lines","map","line","item_id","productId","item_name","name","price","unitAmountCents","quantity","CartLines","props","hostId","showCoupon","checkoutLabel","emptyText","onMutate","siteFetch","useSiteFetch","coupon","setCoupon","email","setEmail","optIn","setOptIn","giftCard","setGiftCard","creditCode","setCreditCode","shipTo","setShipTo","shipCountries","setShipCountries","shipPostal","setShipPostal","askPostal","setAskPostal","status","setStatus","message","setMessage","nativeCheckout","setNativeCheckout","quantityDrafts","setQuantityDrafts","lineKey","variantId","commitQuantity","key","draft","undefined","settle","drafts","_settled","rest","trim","parsed","Math","round","Number","isFinite","max","action","finally","attemptKey","cartSignature","JSON","stringify","extras","extrasSignature","chosenIds","join","fulfillment","current","signature","handleCheckout","globalThis","crypto","randomUUID","Date","now","random","toString","slice","response","method","headers","body","marketingOptIn","couponCode","giftCardCode","credits","length","request","shippingCountry","shippingPostalCode","payload","json","catch","ok","clientSecret","publishableKey","value","subtotalCents","items","String","wallets","readStorefrontCheckoutWallets","url","window","location","assign","paused","parseLockdownRefusal","lockdownRefusalText","extrasChanged","reload","error","fulfillmentChanged","needsShippingCountry","needsShippingPostalCode","shippingCountries","CHECKOUT_SHIPPING_COUNTRIES","variant","color","sx","p","display","flexDirection","gap","imageUrl","siteRelativeMediaSrc","alignItems","component","src","alt","width","height","objectFit","borderRadius","DEFERRED_IMAGE_ATTRIBUTES","bgcolor","flex","minWidth","noWrap","variantLabel","unavailable","onChange","event","target","onBlur","onKeyDown","size","slotProps","htmlInput","inputMode","onClick","justifyContent","offers","chosen","onToggle","toggle","formatCents","state","label","type","helperText","control","checked","placeholder","select","code","CHECKOUT_SHIPPING_COUNTRY_NAMES","autoComplete","maxLength","severity","disabled","every","ready","fallback","payLabel","defaultEmail","onRestart","onCancel","Cart","ref","nodeSx","Array","isArray","useSite","setCart","open","setOpen","refresh","fetch","encodeURIComponent","handler","addEventListener","removeEventListener","viewReported","onScreen","mutate","dispatchEvent","Event","border","borderColor","fontSize","fontFamily","aria-label","badgeContent","count","path","d","anchor","onClose","xs","sm","pb","displayName","schema","$id","pluginId","description","category","ComponentCategory","COMMERCE","icon","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","FieldComponentType","SELECT","options","TEXT_FIELD","CHECKBOX","presets","NodeType","PRESET","data","componentId"],"mappings":"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"}
|
|
@@ -25,6 +25,8 @@ import GiftCardsCard from "./console/gift-cards-card.component.js";
|
|
|
25
25
|
import HostCouponsCard from "./console/host-coupons-card.component.js";
|
|
26
26
|
import HostOrdersCard from "./console/host-orders-card.component.js";
|
|
27
27
|
import LocationsCard from "./console/locations-card.component.js";
|
|
28
|
+
import LocalDeliverySettingsCard from "./console/local-delivery-settings-card.component.js";
|
|
29
|
+
import PickupDeliveryQueueCard from "./console/pickup-delivery-queue-card.component.js";
|
|
28
30
|
import MemberPostsCard from "./console/member-posts-card.component.js";
|
|
29
31
|
import OrderWebhooksCard from "./console/order-webhooks-card.component.js";
|
|
30
32
|
import PaymentsSettingsCard from "./console/payments-settings-card.component.js";
|
|
@@ -48,7 +50,7 @@ import StoreSettingsCard from "./console/store-settings-card.component.js";
|
|
|
48
50
|
import StorefrontTaxSummaryCard from "./console/storefront-tax-summary-card.component.js";
|
|
49
51
|
import SuppliersCard from "./console/suppliers-card.component.js";
|
|
50
52
|
import TaxSettingsCard from "./console/tax-settings-card.component.js";
|
|
51
|
-
import { COMMERCE_SETTINGS_ZONE } from "./console/store-zones.js";
|
|
53
|
+
import { COMMERCE_PROMOTIONS_ZONE, COMMERCE_SETTINGS_ZONE } from "./console/store-zones.js";
|
|
52
54
|
import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot-context";
|
|
53
55
|
/**
|
|
54
56
|
* The `commerceSettings` zone (AGL-3612): other plugins' settings for the
|
|
@@ -61,6 +63,17 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
61
63
|
orgId: undefined
|
|
62
64
|
}) : null;
|
|
63
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* The `commercePromotions` zone (AGL-3640): other plugins' programs beside
|
|
68
|
+
* the store's own money-off surfaces — a rewards program first.
|
|
69
|
+
*/ function CommercePromotionsZone(props) {
|
|
70
|
+
const WidgetSlot = useConsoleWidgetSlot();
|
|
71
|
+
return WidgetSlot ? /*#__PURE__*/ _jsx(WidgetSlot, {
|
|
72
|
+
slot: COMMERCE_PROMOTIONS_ZONE.id,
|
|
73
|
+
hostId: props.hostId,
|
|
74
|
+
orgId: undefined
|
|
75
|
+
}) : null;
|
|
76
|
+
}
|
|
64
77
|
/**
|
|
65
78
|
* The body of one commerce section, built only when that section is the one
|
|
66
79
|
* being read (AGL-2501).
|
|
@@ -125,6 +138,16 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
125
138
|
hostId: hostId
|
|
126
139
|
})
|
|
127
140
|
},
|
|
141
|
+
// What to prepare, hand over and drive out (AGL-3624). Renders
|
|
142
|
+
// nothing for a store with no pickup and no local delivery.
|
|
143
|
+
{
|
|
144
|
+
size: {
|
|
145
|
+
xs: 12
|
|
146
|
+
},
|
|
147
|
+
children: /*#__PURE__*/ _jsx(PickupDeliveryQueueCard, {
|
|
148
|
+
hostId: hostId
|
|
149
|
+
})
|
|
150
|
+
},
|
|
128
151
|
// The two queues that feed orders rather than record them
|
|
129
152
|
// (AGL-2227): checkouts that stalled and shoppers waiting on
|
|
130
153
|
// stock. Beneath the orders list because both are pre-order.
|
|
@@ -188,6 +211,14 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
188
211
|
children: /*#__PURE__*/ _jsx(ReviewsModerationCard, {
|
|
189
212
|
hostId: hostId
|
|
190
213
|
})
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
size: {
|
|
217
|
+
xs: 12
|
|
218
|
+
},
|
|
219
|
+
children: /*#__PURE__*/ _jsx(CommercePromotionsZone, {
|
|
220
|
+
hostId: hostId
|
|
221
|
+
})
|
|
191
222
|
}
|
|
192
223
|
]
|
|
193
224
|
});
|
|
@@ -299,6 +330,16 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
299
330
|
hostId: hostId
|
|
300
331
|
})
|
|
301
332
|
},
|
|
333
|
+
// The store's own delivery (AGL-3624); pickup is per location,
|
|
334
|
+
// on the Inventory locations card above.
|
|
335
|
+
{
|
|
336
|
+
size: {
|
|
337
|
+
xs: 12
|
|
338
|
+
},
|
|
339
|
+
children: /*#__PURE__*/ _jsx(LocalDeliverySettingsCard, {
|
|
340
|
+
hostId: hostId
|
|
341
|
+
})
|
|
342
|
+
},
|
|
302
343
|
{
|
|
303
344
|
size: {
|
|
304
345
|
xs: 12
|