@aglyn/plugins-commerce 1.0.0-beta.285 → 1.0.0-beta.288
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/README.md +1 -1
- package/package.json +13 -13
- package/src/lib/components/cart.js +25 -12
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +70 -13
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +2 -1
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js.map +1 -1
- package/src/lib/components/console/payment-methods-card.component.js +1 -1
- package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
- package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
- package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
- package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
- package/src/lib/components/console/pos/use-pos-display.js +50 -0
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
- package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
- package/src/lib/components/console/pos-cellular-control.component.js +211 -0
- package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
- package/src/lib/components/console/pos-devices-card.component.js +47 -15
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
- package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
- package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-display-page.component.js +44 -2
- package/src/lib/components/console/pos-display-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
- package/src/lib/components/console/pos-hardware-card.component.js +157 -36
- package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.d.ts +1 -1
- package/src/lib/components/console/pos-page.component.js +63 -12
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
- package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
- package/src/lib/components/console/product-check-in-fields.component.js +60 -14
- package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +44 -1
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
- package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
- package/src/lib/components/console/product-register-fields.component.js +31 -2
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +11 -2
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
- package/src/lib/components/console/register-hardware-card.component.js +56 -27
- package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +9 -0
- package/src/lib/components/console/reservations-card.component.js +158 -23
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
- package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
- package/src/lib/components/console/shipstation-card.component.js +3 -3
- package/src/lib/components/console/shipstation-card.component.js.map +1 -1
- package/src/lib/components/product-detail.d.ts +4 -0
- package/src/lib/components/product-detail.js +40 -5
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-reviews.js +28 -11
- package/src/lib/components/product-reviews.js.map +1 -1
- package/src/lib/components/reservation-widget.js +28 -5
- package/src/lib/components/reservation-widget.js.map +1 -1
- package/src/lib/components/use-day-picker.d.ts +25 -0
- package/src/lib/components/use-day-picker.js +57 -0
- package/src/lib/components/use-day-picker.js.map +1 -0
- package/src/lib/constants/operator-alerts.d.ts +55 -0
- package/src/lib/constants/operator-alerts.js +156 -1
- package/src/lib/constants/operator-alerts.js.map +1 -1
- package/src/lib/declarations.console-server.js +54 -1
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +4 -2
- package/src/lib/declarations.js +15 -4
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/declarations.server.js +9 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/commerce-cart.d.ts +9 -1
- package/src/lib/model/commerce-cart.js +4 -3
- package/src/lib/model/commerce-cart.js.map +1 -1
- package/src/lib/model/commerce-check-in-product.d.ts +26 -0
- package/src/lib/model/commerce-check-in-product.js +64 -2
- package/src/lib/model/commerce-check-in-product.js.map +1 -1
- package/src/lib/model/commerce-check-in-record.d.ts +127 -0
- package/src/lib/model/commerce-check-in-record.js +36 -0
- package/src/lib/model/commerce-check-in-record.js.map +1 -0
- package/src/lib/model/commerce-check-in.d.ts +91 -87
- package/src/lib/model/commerce-check-in.js +186 -62
- package/src/lib/model/commerce-check-in.js.map +1 -1
- package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
- package/src/lib/model/commerce-kiosk-offer.js +35 -0
- package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +76 -0
- package/src/lib/model/commerce-orders.js +6 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
- package/src/lib/model/commerce-pos-day-report.js +39 -2
- package/src/lib/model/commerce-pos-day-report.js.map +1 -1
- package/src/lib/model/commerce-pos-offline.d.ts +1 -1
- package/src/lib/model/commerce-pos-offline.js +6 -1
- package/src/lib/model/commerce-pos-offline.js.map +1 -1
- package/src/lib/model/commerce-pos-ops.js +3 -2
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +36 -3
- package/src/lib/model/commerce-pos.js +14 -6
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-receipt.js +3 -2
- package/src/lib/model/commerce-receipt.js.map +1 -1
- package/src/lib/model/commerce-reservations.d.ts +69 -4
- package/src/lib/model/commerce-reservations.js +57 -5
- package/src/lib/model/commerce-reservations.js.map +1 -1
- package/src/lib/model/commerce.d.ts +66 -0
- package/src/lib/model/commerce.js +15 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/order-list-fields.d.ts +11 -0
- package/src/lib/model/order-list-fields.js +17 -1
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/own-store-tax-summary.d.ts +152 -0
- package/src/lib/model/own-store-tax-summary.js +288 -0
- package/src/lib/model/own-store-tax-summary.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +74 -0
- package/src/lib/model/plugin-permissions.js +224 -7
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/model/pos-cellular.d.ts +223 -0
- package/src/lib/model/pos-cellular.js +293 -0
- package/src/lib/model/pos-cellular.js.map +1 -0
- package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
- package/src/lib/model/pos-hardware-in-person.js +224 -0
- package/src/lib/model/pos-hardware-in-person.js.map +1 -0
- package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
- package/src/lib/model/pos-hardware-tax-summary.js +225 -0
- package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
- package/src/lib/model/pos-hardware-terms.d.ts +74 -0
- package/src/lib/model/pos-hardware-terms.js +115 -0
- package/src/lib/model/pos-hardware-terms.js.map +1 -0
- package/src/lib/model/pos-hardware.d.ts +349 -7
- package/src/lib/model/pos-hardware.js +291 -20
- package/src/lib/model/pos-hardware.js.map +1 -1
- package/src/lib/model/product-write.d.ts +10 -0
- package/src/lib/model/product-write.js +4 -2
- package/src/lib/model/product-write.js.map +1 -1
- package/src/lib/model/workspace-site-permissions.d.ts +26 -0
- package/src/lib/model/workspace-site-permissions.js +81 -0
- package/src/lib/model/workspace-site-permissions.js.map +1 -0
- package/src/lib/plugin.js +16 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/billing-webhook.js +25 -1
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cancel-order.js +7 -5
- package/src/lib/server/cancel-order.js.map +1 -1
- package/src/lib/server/cart-checkout.js +20 -8
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.js +29 -0
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/checkout.js +42 -13
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/collection-membership.d.ts +4 -0
- package/src/lib/server/collection-membership.js +5 -10
- package/src/lib/server/collection-membership.js.map +1 -1
- package/src/lib/server/commerce-site-keys.d.ts +48 -0
- package/src/lib/server/commerce-site-keys.js +61 -0
- package/src/lib/server/commerce-site-keys.js.map +1 -0
- package/src/lib/server/draft-order.js +8 -5
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/fulfill-order.js +7 -5
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/gift-cards.js +8 -5
- package/src/lib/server/gift-cards.js.map +1 -1
- package/src/lib/server/local-fulfillment-status.js +9 -6
- package/src/lib/server/local-fulfillment-status.js.map +1 -1
- package/src/lib/server/member-post.js +6 -5
- package/src/lib/server/member-post.js.map +1 -1
- package/src/lib/server/membership-admin-password.d.ts +4 -2
- package/src/lib/server/membership-admin-password.js +10 -8
- package/src/lib/server/membership-admin-password.js.map +1 -1
- package/src/lib/server/membership-admin-remove.d.ts +7 -5
- package/src/lib/server/membership-admin-remove.js +9 -9
- package/src/lib/server/membership-admin-remove.js.map +1 -1
- package/src/lib/server/order-notifications.js +5 -2
- package/src/lib/server/order-notifications.js.map +1 -1
- package/src/lib/server/order-print.js +7 -5
- package/src/lib/server/order-print.js.map +1 -1
- package/src/lib/server/order-receipt-send.js +8 -5
- package/src/lib/server/order-receipt-send.js.map +1 -1
- package/src/lib/server/order-webhooks.js +8 -8
- package/src/lib/server/order-webhooks.js.map +1 -1
- package/src/lib/server/orders-shipping-prepare.js +9 -6
- package/src/lib/server/orders-shipping-prepare.js.map +1 -1
- package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
- package/src/lib/server/own-store-tax-return-source.js +312 -0
- package/src/lib/server/own-store-tax-return-source.js.map +1 -0
- package/src/lib/server/payment-methods.js +13 -9
- package/src/lib/server/payment-methods.js.map +1 -1
- package/src/lib/server/pos-auth.d.ts +37 -6
- package/src/lib/server/pos-auth.js +40 -15
- package/src/lib/server/pos-auth.js.map +1 -1
- package/src/lib/server/pos-cellular-billing.d.ts +81 -0
- package/src/lib/server/pos-cellular-billing.js +711 -0
- package/src/lib/server/pos-cellular-billing.js.map +1 -0
- package/src/lib/server/pos-cellular-notify.d.ts +47 -0
- package/src/lib/server/pos-cellular-notify.js +150 -0
- package/src/lib/server/pos-cellular-notify.js.map +1 -0
- package/src/lib/server/pos-cellular.d.ts +88 -0
- package/src/lib/server/pos-cellular.js +339 -0
- package/src/lib/server/pos-cellular.js.map +1 -0
- package/src/lib/server/pos-check-in.d.ts +5 -1
- package/src/lib/server/pos-check-in.js +296 -28
- package/src/lib/server/pos-check-in.js.map +1 -1
- package/src/lib/server/pos-day-report.js +29 -3
- package/src/lib/server/pos-day-report.js.map +1 -1
- package/src/lib/server/pos-display.d.ts +16 -0
- package/src/lib/server/pos-display.js +129 -2
- package/src/lib/server/pos-display.js.map +1 -1
- package/src/lib/server/pos-hardware-admin.d.ts +10 -1
- package/src/lib/server/pos-hardware-admin.js +250 -84
- package/src/lib/server/pos-hardware-admin.js.map +1 -1
- package/src/lib/server/pos-hardware-attach.d.ts +105 -0
- package/src/lib/server/pos-hardware-attach.js +443 -0
- package/src/lib/server/pos-hardware-attach.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
- package/src/lib/server/pos-hardware-buyer-record.js +86 -0
- package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
- package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
- package/src/lib/server/pos-hardware-cancel.js +147 -0
- package/src/lib/server/pos-hardware-cancel.js.map +1 -0
- package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
- package/src/lib/server/pos-hardware-closure-notices.js +85 -0
- package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
- package/src/lib/server/pos-hardware-closure.d.ts +60 -0
- package/src/lib/server/pos-hardware-closure.js +153 -0
- package/src/lib/server/pos-hardware-closure.js.map +1 -0
- package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
- package/src/lib/server/pos-hardware-in-person.js +236 -0
- package/src/lib/server/pos-hardware-in-person.js.map +1 -0
- package/src/lib/server/pos-hardware-notify.d.ts +40 -2
- package/src/lib/server/pos-hardware-notify.js +195 -14
- package/src/lib/server/pos-hardware-notify.js.map +1 -1
- package/src/lib/server/pos-hardware-readers.d.ts +115 -0
- package/src/lib/server/pos-hardware-readers.js +430 -0
- package/src/lib/server/pos-hardware-readers.js.map +1 -0
- package/src/lib/server/pos-hardware-returns.d.ts +116 -0
- package/src/lib/server/pos-hardware-returns.js +502 -0
- package/src/lib/server/pos-hardware-returns.js.map +1 -0
- package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
- package/src/lib/server/pos-hardware-sale-fields.js +44 -0
- package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
- package/src/lib/server/pos-hardware-sale.d.ts +54 -0
- package/src/lib/server/pos-hardware-sale.js +369 -0
- package/src/lib/server/pos-hardware-sale.js.map +1 -0
- package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
- package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
- package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
- package/src/lib/server/pos-hardware-terms.d.ts +64 -0
- package/src/lib/server/pos-hardware-terms.js +154 -0
- package/src/lib/server/pos-hardware-terms.js.map +1 -0
- package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
- package/src/lib/server/pos-hardware-user-eraser.js +31 -7
- package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
- package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
- package/src/lib/server/pos-hardware-webhook.js +51 -6
- package/src/lib/server/pos-hardware-webhook.js.map +1 -1
- package/src/lib/server/pos-hardware.d.ts +74 -1
- package/src/lib/server/pos-hardware.js +175 -10
- package/src/lib/server/pos-hardware.js.map +1 -1
- package/src/lib/server/pos-kiosk.d.ts +2 -0
- package/src/lib/server/pos-kiosk.js +17 -12
- package/src/lib/server/pos-kiosk.js.map +1 -1
- package/src/lib/server/pos-offline-card-order.d.ts +64 -0
- package/src/lib/server/pos-offline-card-order.js +102 -0
- package/src/lib/server/pos-offline-card-order.js.map +1 -0
- package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
- package/src/lib/server/pos-offline-card-reconcile.js +215 -18
- package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
- package/src/lib/server/pos-offline-sync.d.ts +39 -0
- package/src/lib/server/pos-offline-sync.js +190 -55
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-ops-gate.d.ts +28 -9
- package/src/lib/server/pos-ops-gate.js +50 -19
- package/src/lib/server/pos-ops-gate.js.map +1 -1
- package/src/lib/server/pos-ops-routes.js +24 -0
- package/src/lib/server/pos-ops-routes.js.map +1 -1
- package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
- package/src/lib/server/pos-order-refund-ids.js +31 -0
- package/src/lib/server/pos-order-refund-ids.js.map +1 -0
- package/src/lib/server/pos-order.js +52 -49
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.js +1 -1
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-reader-splash-admin.js +30 -32
- package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
- package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
- package/src/lib/server/pos-reader-splash-images-route.js +113 -0
- package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
- package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
- package/src/lib/server/pos-reader-splash-images.js +123 -0
- package/src/lib/server/pos-reader-splash-images.js.map +1 -0
- package/src/lib/server/pos-reader-splash.d.ts +68 -1
- package/src/lib/server/pos-reader-splash.js +182 -11
- package/src/lib/server/pos-reader-splash.js.map +1 -1
- package/src/lib/server/pos-readers.d.ts +29 -0
- package/src/lib/server/pos-readers.js +134 -35
- package/src/lib/server/pos-readers.js.map +1 -1
- package/src/lib/server/pos-refund-authority.d.ts +3 -1
- package/src/lib/server/pos-refund-authority.js +3 -2
- package/src/lib/server/pos-refund-authority.js.map +1 -1
- package/src/lib/server/pos-return.d.ts +10 -0
- package/src/lib/server/pos-return.js +29 -7
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/pos-sale.js +6 -1
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-shift.js +11 -0
- package/src/lib/server/pos-shift.js.map +1 -1
- package/src/lib/server/pos-staff-pin.js +29 -24
- package/src/lib/server/pos-staff-pin.js.map +1 -1
- package/src/lib/server/pos-terminal.d.ts +14 -4
- package/src/lib/server/pos-terminal.js +34 -38
- package/src/lib/server/pos-terminal.js.map +1 -1
- package/src/lib/server/printers.d.ts +7 -3
- package/src/lib/server/printers.js +18 -12
- package/src/lib/server/printers.js.map +1 -1
- package/src/lib/server/product-drafts.d.ts +11 -1
- package/src/lib/server/product-drafts.js +12 -8
- package/src/lib/server/product-drafts.js.map +1 -1
- package/src/lib/server/product.d.ts +15 -1
- package/src/lib/server/product.js +16 -3
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/products-write.d.ts +26 -2
- package/src/lib/server/products-write.js +19 -7
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server/refund.js +55 -42
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/reservation-availability-query.d.ts +8 -0
- package/src/lib/server/reservation-availability-query.js +11 -1
- package/src/lib/server/reservation-availability-query.js.map +1 -1
- package/src/lib/server/reservation-availability.d.ts +1 -1
- package/src/lib/server/reservation-availability.js +7 -2
- package/src/lib/server/reservation-availability.js.map +1 -1
- package/src/lib/server/reservation-guests.d.ts +32 -0
- package/src/lib/server/reservation-guests.js +285 -0
- package/src/lib/server/reservation-guests.js.map +1 -0
- package/src/lib/server/reservation-walk-in.d.ts +11 -1
- package/src/lib/server/reservation-walk-in.js +56 -12
- package/src/lib/server/reservation-walk-in.js.map +1 -1
- package/src/lib/server/reserve.js +18 -5
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/returns.js +9 -6
- package/src/lib/server/returns.js.map +1 -1
- package/src/lib/server/reviews.d.ts +22 -2
- package/src/lib/server/reviews.js +88 -20
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/shipping-connectors.js +10 -11
- package/src/lib/server/shipping-connectors.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +20 -3
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server/store-day.d.ts +33 -0
- package/src/lib/server/store-day.js +46 -0
- package/src/lib/server/store-day.js.map +1 -0
- package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
- package/src/lib/server/store-setup-ai-writer.js +5 -6
- package/src/lib/server/store-setup-ai-writer.js.map +1 -1
- package/src/lib/server/storefront-tax.d.ts +13 -0
- package/src/lib/server/storefront-tax.js +8 -1
- package/src/lib/server/storefront-tax.js.map +1 -1
- package/src/lib/server/tax-return-source.d.ts +32 -3
- package/src/lib/server/tax-return-source.js +99 -20
- package/src/lib/server/tax-return-source.js.map +1 -1
- package/src/lib/server.js +100 -2
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/fake-firestore.js +58 -16
- package/src/lib/testing/fake-firestore.js.map +1 -1
- package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
- package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
- package/src/lib/testing/site-register-permissions.d.ts +29 -0
- package/src/lib/testing/site-register-permissions.js +38 -0
- package/src/lib/testing/site-register-permissions.js.map +1 -0
- package/src/lib/transfer/tracking.server.js +8 -5
- package/src/lib/transfer/tracking.server.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +2 -0
- package/src/lib/utils/add-to-cart.js +6 -3
- package/src/lib/utils/add-to-cart.js.map +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-cellular-control.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Checkbox,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useState } from 'react'\nimport type { PosCellularView } from '../../model/pos-cellular'\nimport { posReadersCall, PosRequestError, usd } from './pos/pos-api'\n\nexport interface PosCellularControlProps {\n hostId: string\n cellular: PosCellularView\n /** Why the viewer may not change it (\"Registers and devices\"), or null. */\n blocked: string | null\n /** Reload the card once it changed. */\n onChanged: () => void | Promise<void>\n}\n\nconst readersText = (count: number) => `${count} Stripe Reader S710${count === 1 ? '' : 's'}`\n\n/**\n * 4G for a store's Stripe Reader S710s (AGL-4038), on the POS devices card.\n * Stripe turns cellular service on for a store's reader Location, so this is\n * one switch for the store: it says plainly that every S710 at the store\n * gets 4G and that each one is charged, and turning it on takes an explicit\n * agreement to the monthly price. Turning it ON is charged to the workspace,\n * so it also takes \"Manage billing\": without it the control says so rather\n * than hiding. A store whose 4G was turned off for an unpaid month says\n * which, and how to turn it back on. Loaded only where 4G is offered and the\n * store has an S710.\n */\nexport function PosCellularControl({ hostId, cellular, blocked, onChanged }: PosCellularControlProps) {\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const [dialog, setDialog] = useState<'on' | 'off' | null>(null)\n const [agreed, setAgreed] = useState(false)\n const [busy, setBusy] = useState(false)\n const price = usd(cellular.readerMonthlyCents)\n // Off needs only the card's key; on is charged to the workspace, so billing too.\n const reason = blocked ?? (cellular.enabled ? null : (cellular.turnOnBlocked ?? null))\n\n const change = async (enabled: boolean) => {\n if (!user) return\n setBusy(true)\n try {\n await posReadersCall(user, { action: 'cellular', hostId, enabled, ...(enabled ? { consent: agreed } : {}) })\n setDialog(null)\n setAgreed(false)\n enqueueSnackbar(enabled ? '4G is on for this store’s S710 readers' : '4G is off for this store', {\n variant: 'success',\n persist: false,\n })\n await onChanged()\n } catch (error) {\n enqueueSnackbar(error instanceof PosRequestError ? error.message : '4G could not be changed. Try again.', {\n variant: 'warning',\n persist: false,\n })\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}>\n <Box sx={{ flex: 1, minWidth: 220 }}>\n <Typography variant=\"body2\" sx={{ fontWeight: 'fontWeightMedium' }}>\n {'4G (cellular)'}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {cellular.enabled\n ? `On for every Stripe Reader S710 at this store (${readersText(cellular.readers)} now). Each is charged ${price} a month.`\n : `A Stripe Reader S710 can use Stripe's 4G service when Wi-Fi drops. It turns on for every S710 at this store, at ${price} a month each.`}\n </Typography>\n </Box>\n <Chip size=\"small\" label={cellular.enabled ? 'On' : 'Off'} color={cellular.enabled ? 'success' : 'default'} />\n <BlockedControl blocked={Boolean(reason)} reason={reason ?? ''}>\n <Button size=\"small\" onClick={() => setDialog(cellular.enabled ? 'off' : 'on')}>\n {cellular.enabled ? 'Turn off 4G' : 'Turn on 4G'}\n </Button>\n </BlockedControl>\n {cellular.suspended ? (\n <Alert severity=\"warning\" sx={{ flexBasis: '100%' }}>\n {`4G was turned off because the 4G charge for ${cellular.suspended.month} wasn't paid. Pay it on the Billing page, then turn 4G on again here.`}\n </Alert>\n ) : null}\n\n <Dialog open={dialog === 'on'} onClose={() => (busy ? undefined : setDialog(null))} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{'Turn on 4G for this store?'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>\n <Typography variant=\"body2\">\n {`Every Stripe Reader S710 at this store gets Stripe's 4G service and uses it whenever Wi-Fi and Ethernet are not available. That is ${readersText(cellular.readers)} now, and any S710 you add here later.`}\n </Typography>\n <Typography variant=\"body2\">\n {`Each S710 is charged ${price} a month, plus any sales tax, for every calendar month it has 4G. The charge goes to this workspace's card at the start of the next month. Turning 4G off stops the charge from the next month. If a month's charge isn't paid, 4G is turned off after a grace period, until it's paid and turned on again.`}\n </Typography>\n <FormControlLabel\n control={<Checkbox checked={agreed} onChange={(event) => setAgreed(event.target.checked)} />}\n label={`I agree to ${price} a month for each Stripe Reader S710 at this store while 4G is on.`}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDialog(null)} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button variant=\"contained\" disabled={busy || !agreed} onClick={() => void change(true)}>\n {'Turn on 4G'}\n </Button>\n </DialogActions>\n </Dialog>\n\n <Dialog open={dialog === 'off'} onClose={() => (busy ? undefined : setDialog(null))} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Turn off 4G?'}</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\">\n {'The S710 readers at this store stop using 4G the next time they connect, and use Wi-Fi or Ethernet only. This month is still charged for each reader that had 4G in it.'}\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDialog(null)} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button variant=\"contained\" disabled={busy} onClick={() => void change(false)}>\n {'Turn off 4G'}\n </Button>\n </DialogActions>\n </Dialog>\n </Stack>\n )\n}\nPosCellularControl.displayName = 'PosCellularControl'\n\nexport default PosCellularControl\n"],"names":["BlockedControl","useSnackbar","useUser","Alert","Box","Button","Checkbox","Chip","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","Stack","Typography","useState","posReadersCall","PosRequestError","usd","readersText","count","PosCellularControl","hostId","cellular","blocked","onChanged","data","user","enqueueSnackbar","dialog","setDialog","agreed","setAgreed","busy","setBusy","price","readerMonthlyCents","reason","enabled","turnOnBlocked","change","action","consent","variant","persist","error","message","direction","spacing","sx","alignItems","flexWrap","rowGap","flex","minWidth","fontWeight","color","component","readers","size","label","Boolean","onClick","suspended","severity","flexBasis","month","open","onClose","undefined","maxWidth","fullWidth","display","flexDirection","gap","control","checked","onChange","event","target","disabled","displayName"],"mappings":"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"}
|
|
@@ -7,6 +7,14 @@ export interface PosDevicesCardProps {
|
|
|
7
7
|
* rather than offering a button that fails. Absent reads as not allowed.
|
|
8
8
|
*/
|
|
9
9
|
canManagePos?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether the viewer may set the register's devices up (AGL-4047): the
|
|
12
|
+
* "Registers and devices" key on top of `canManagePos`. Adding, renaming,
|
|
13
|
+
* moving and removing a reader, pairing a display and signing one out are
|
|
14
|
+
* refused by the server without it, so each control says why. Absent
|
|
15
|
+
* follows `canManagePos`.
|
|
16
|
+
*/
|
|
17
|
+
canSetUpDevices?: boolean;
|
|
10
18
|
}
|
|
11
19
|
/**
|
|
12
20
|
* The register's hardware (AGL-3607, AGL-3608): Stripe Terminal card readers
|
|
@@ -18,7 +26,7 @@ export interface PosDevicesCardProps {
|
|
|
18
26
|
* through the same flow as the register's own Pair display (AGL-3712); a site
|
|
19
27
|
* with no register is sent to the card that makes one.
|
|
20
28
|
*/
|
|
21
|
-
export declare function PosDevicesCard({ hostId, canManagePos }: PosDevicesCardProps): import("react").JSX.Element;
|
|
29
|
+
export declare function PosDevicesCard({ hostId, canManagePos, canSetUpDevices, }: PosDevicesCardProps): import("react").JSX.Element;
|
|
22
30
|
export declare namespace PosDevicesCard {
|
|
23
31
|
var displayName: string;
|
|
24
32
|
}
|
|
@@ -19,15 +19,18 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
19
19
|
import * as Aglyn from "@aglyn/aglyn";
|
|
20
20
|
import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
21
21
|
import { CardDisplay, useConfirmationContext } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
|
|
22
23
|
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
23
24
|
import { useFirestore, useFirestoreCollection, useOrgPlan, useUser } from "@aglyn/tenant-feature-instance";
|
|
24
25
|
import { Box, Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, MenuItem, Stack, TextField, Typography } from "@mui/material";
|
|
25
26
|
import { collection, limit, query } from "firebase/firestore";
|
|
26
|
-
import { useCallback, useEffect, useState } from "react";
|
|
27
|
+
import { lazy, Suspense, useCallback, useEffect, useState } from "react";
|
|
27
28
|
import { posDisplayCall, posReadersCall, PosRequestError } from "./pos/pos-api.js";
|
|
28
29
|
import { POS_DEVICES_ANCHOR } from "./pos/pos-kiosk-readiness.component.js";
|
|
29
30
|
import { POS_REGISTERS_ANCHOR, usePosPairing } from "./pos/pos-pairing.component.js";
|
|
30
31
|
import { PosReaderSplashSetting } from "./pos-reader-splash-setting.component.js";
|
|
32
|
+
/** Drawn only where 4G is offered, so it arrives with the first store that shows it. */ const PosCellularControl = /*#__PURE__*/ lazy(()=>import("./pos-cellular-control.component.js"));
|
|
33
|
+
/** Why a device control is not offered to someone who works the register. */ const DEVICES_KEY_REASON = 'Only a member with the "Registers and devices" permission can set up card readers, displays and kiosks.';
|
|
31
34
|
const EMPTY_ADDRESS = {
|
|
32
35
|
line1: '',
|
|
33
36
|
line2: '',
|
|
@@ -45,8 +48,9 @@ const EMPTY_ADDRESS = {
|
|
|
45
48
|
* Each register pairs a new customer display or self-service kiosk here,
|
|
46
49
|
* through the same flow as the register's own Pair display (AGL-3712); a site
|
|
47
50
|
* with no register is sent to the card that makes one.
|
|
48
|
-
*/ export function PosDevicesCard({ hostId, canManagePos = false }) {
|
|
51
|
+
*/ export function PosDevicesCard({ hostId, canManagePos = false, canSetUpDevices = canManagePos }) {
|
|
49
52
|
var _ref, _ref1, _ref2;
|
|
53
|
+
var _answer_cellular;
|
|
50
54
|
const firestore = useFirestore();
|
|
51
55
|
const { data: user } = useUser();
|
|
52
56
|
const { enqueueSnackbar } = useSnackbar();
|
|
@@ -93,7 +97,8 @@ const EMPTY_ADDRESS = {
|
|
|
93
97
|
hostId,
|
|
94
98
|
onError: onPairingError
|
|
95
99
|
});
|
|
96
|
-
/** Why pairing is not offered to this viewer, or null when it is. */ const pairBlocked = !planReady ? 'Checking your plan…' : !posEntitled ? 'Point of Sale is not on your plan. Upgrade in Billing to pair displays and kiosks.' : !canManagePos ? 'Only an admin or editor with the "Use the point of sale" permission can pair displays and kiosks.' : null;
|
|
100
|
+
/** Why pairing is not offered to this viewer, or null when it is. */ const pairBlocked = !planReady ? 'Checking your plan…' : !posEntitled ? 'Point of Sale is not on your plan. Upgrade in Billing to pair displays and kiosks.' : !canManagePos ? 'Only an admin or editor with the "Use the point of sale" permission can pair displays and kiosks.' : !canSetUpDevices ? DEVICES_KEY_REASON : null;
|
|
101
|
+
/** Why the reader controls are not offered, or null when they are. */ const readersBlocked = !canManagePos ? 'Only an admin or editor with the "Use the point of sale" permission can set up card readers.' : !canSetUpDevices ? DEVICES_KEY_REASON : null;
|
|
97
102
|
const load = useCallback(async (refresh = false)=>{
|
|
98
103
|
if (!user) return;
|
|
99
104
|
try {
|
|
@@ -205,10 +210,14 @@ const EMPTY_ADDRESS = {
|
|
|
205
210
|
href: `#${POS_REGISTERS_ANCHOR}`,
|
|
206
211
|
children: 'Add a register'
|
|
207
212
|
}) : null,
|
|
208
|
-
showReaders ? /*#__PURE__*/ _jsx(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
children:
|
|
213
|
+
showReaders ? /*#__PURE__*/ _jsx(BlockedControl, {
|
|
214
|
+
blocked: Boolean(readersBlocked),
|
|
215
|
+
reason: readersBlocked != null ? readersBlocked : '',
|
|
216
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
217
|
+
size: "small",
|
|
218
|
+
onClick: ()=>setAdding(true),
|
|
219
|
+
children: 'Add card reader'
|
|
220
|
+
})
|
|
212
221
|
}) : null
|
|
213
222
|
]
|
|
214
223
|
})
|
|
@@ -266,6 +275,7 @@ const EMPTY_ADDRESS = {
|
|
|
266
275
|
select: true,
|
|
267
276
|
size: "small",
|
|
268
277
|
label: "Register",
|
|
278
|
+
disabled: Boolean(readersBlocked),
|
|
269
279
|
value: (_reader_registerId = reader.registerId) != null ? _reader_registerId : '',
|
|
270
280
|
onChange: async (event)=>{
|
|
271
281
|
if (!user) return;
|
|
@@ -295,17 +305,23 @@ const EMPTY_ADDRESS = {
|
|
|
295
305
|
}, register.$id))
|
|
296
306
|
]
|
|
297
307
|
}),
|
|
298
|
-
/*#__PURE__*/ _jsx(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
/*#__PURE__*/ _jsx(BlockedControl, {
|
|
309
|
+
blocked: Boolean(readersBlocked),
|
|
310
|
+
reason: readersBlocked != null ? readersBlocked : '',
|
|
311
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
312
|
+
size: "small",
|
|
313
|
+
onClick: ()=>setRenaming({
|
|
314
|
+
id: reader.id,
|
|
315
|
+
label: reader.label
|
|
316
|
+
}),
|
|
317
|
+
children: 'Rename'
|
|
318
|
+
})
|
|
305
319
|
}),
|
|
306
320
|
/*#__PURE__*/ _jsx(Button, {
|
|
307
321
|
size: "small",
|
|
308
322
|
color: "error",
|
|
323
|
+
disabled: Boolean(readersBlocked),
|
|
324
|
+
title: readersBlocked != null ? readersBlocked : undefined,
|
|
309
325
|
onClick: async ()=>{
|
|
310
326
|
const confirmed = await confirm({
|
|
311
327
|
title: 'Remove this card reader?',
|
|
@@ -334,9 +350,18 @@ const EMPTY_ADDRESS = {
|
|
|
334
350
|
})
|
|
335
351
|
]
|
|
336
352
|
}) : null,
|
|
353
|
+
showReaders && (answer == null ? void 0 : answer.cellular) ? /*#__PURE__*/ _jsx(Suspense, {
|
|
354
|
+
fallback: null,
|
|
355
|
+
children: /*#__PURE__*/ _jsx(PosCellularControl, {
|
|
356
|
+
hostId: hostId,
|
|
357
|
+
cellular: answer.cellular,
|
|
358
|
+
blocked: readersBlocked,
|
|
359
|
+
onChanged: ()=>load()
|
|
360
|
+
})
|
|
361
|
+
}) : null,
|
|
337
362
|
showReaders ? /*#__PURE__*/ _jsx(PosReaderSplashSetting, {
|
|
338
363
|
hostId: hostId,
|
|
339
|
-
canManagePos: canManagePos
|
|
364
|
+
canManagePos: canManagePos && canSetUpDevices
|
|
340
365
|
}) : null,
|
|
341
366
|
/*#__PURE__*/ _jsxs(Stack, {
|
|
342
367
|
spacing: 1,
|
|
@@ -409,6 +434,8 @@ const EMPTY_ADDRESS = {
|
|
|
409
434
|
/*#__PURE__*/ _jsx(Button, {
|
|
410
435
|
size: "small",
|
|
411
436
|
color: "error",
|
|
437
|
+
disabled: Boolean(pairBlocked),
|
|
438
|
+
title: pairBlocked != null ? pairBlocked : undefined,
|
|
412
439
|
onClick: async ()=>{
|
|
413
440
|
if (!user) return;
|
|
414
441
|
try {
|
|
@@ -518,6 +545,11 @@ const EMPTY_ADDRESS = {
|
|
|
518
545
|
},
|
|
519
546
|
children: 'On the reader, open Settings and choose Generate pairing code, then enter the code it shows.'
|
|
520
547
|
}),
|
|
548
|
+
(answer == null ? void 0 : (_answer_cellular = answer.cellular) == null ? void 0 : _answer_cellular.enabled) ? /*#__PURE__*/ _jsx(Typography, {
|
|
549
|
+
variant: "body2",
|
|
550
|
+
color: "text.secondary",
|
|
551
|
+
children: '4G is on at this store: a Stripe Reader S710 you add gets it too, and is charged for it each month.'
|
|
552
|
+
}) : null,
|
|
521
553
|
/*#__PURE__*/ _jsx(TextField, {
|
|
522
554
|
label: "Registration code",
|
|
523
555
|
value: code,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-devices-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, useFirestoreCollection, useOrgPlan, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, limit, query } from 'firebase/firestore'\nimport { useCallback, useEffect, useState } from 'react'\nimport { posDisplayCall, posReadersCall, PosRequestError } from './pos/pos-api'\nimport { POS_DEVICES_ANCHOR } from './pos/pos-kiosk-readiness.component'\nimport { POS_REGISTERS_ANCHOR, usePosPairing } from './pos/pos-pairing.component'\nimport { PosReaderSplashSetting } from './pos-reader-splash-setting.component'\n\ninterface ReaderRow {\n id: string\n label: string\n registerId: string | null\n deviceType: string | null\n serialNumber: string | null\n status: string\n livemode: boolean\n}\n\ninterface ReadersAnswer {\n available: boolean\n testMode: boolean\n locationReady: boolean\n readers: ReaderRow[]\n}\n\ninterface DisplayRow {\n id: string\n label: string\n createdAtMs: number\n lastSeenAtMs: number\n}\n\nexport interface PosDevicesCardProps {\n hostId: string\n /**\n * Whether the viewer may work this site's register: `managePos`, as the\n * shell resolved it, on a site role that may run it (admin or editor).\n * Pairing a tablet is refused by the server otherwise, so the card says why\n * rather than offering a button that fails. Absent reads as not allowed.\n */\n canManagePos?: boolean\n}\n\nconst EMPTY_ADDRESS = { line1: '', line2: '', city: '', state: '', postalCode: '', country: 'US' }\n\n/**\n * The register's hardware (AGL-3607, AGL-3608): Stripe Terminal card readers\n * — registered with the code a reader shows, bound to a register, renamed,\n * removed — and the customer displays paired to each register, which can be\n * signed out. Readers appear only where card readers are offered at all.\n *\n * Each register pairs a new customer display or self-service kiosk here,\n * through the same flow as the register's own Pair display (AGL-3712); a site\n * with no register is sent to the card that makes one.\n */\nexport function PosDevicesCard({ hostId, canManagePos = false }: PosDevicesCardProps) {\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const { data: registerDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'registers'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n // Not \"no registers\" until the listen has answered.\n const noRegisters = registerDocs !== undefined && registerDocs.length === 0\n const registers = [...(registerDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n const [answer, setAnswer] = useState<ReadersAnswer | null>(null)\n const [displays, setDisplays] = useState<Record<string, DisplayRow[]>>({})\n const [adding, setAdding] = useState(false)\n const [code, setCode] = useState('')\n const [label, setLabel] = useState('')\n const [registerId, setRegisterId] = useState('')\n const [address, setAddress] = useState(EMPTY_ADDRESS)\n const [busy, setBusy] = useState(false)\n const [renaming, setRenaming] = useState<{ id: string; label: string } | null>(null)\n const { org, ready: planReady } = useOrgPlan(hostId)\n const posEntitled = planReady && Aglyn.checkEntitlement(org as any, 'pos')\n\n const notify = useCallback(\n (error: unknown, fallback: string) =>\n enqueueSnackbar(error instanceof PosRequestError ? error.message : fallback, {\n variant: 'warning',\n persist: false,\n }),\n [enqueueSnackbar],\n )\n\n const onPairingError = useCallback(\n (message: string) => enqueueSnackbar(message, { variant: 'warning', persist: false }),\n [enqueueSnackbar],\n )\n const pairingFlow = usePosPairing({ user, hostId, onError: onPairingError })\n /** Why pairing is not offered to this viewer, or null when it is. */\n const pairBlocked = !planReady\n ? 'Checking your plan…'\n : !posEntitled\n ? 'Point of Sale is not on your plan. Upgrade in Billing to pair displays and kiosks.'\n : !canManagePos\n ? 'Only an admin or editor with the \"Use the point of sale\" permission can pair displays and kiosks.'\n : null\n\n const load = useCallback(\n async (refresh = false) => {\n if (!user) return\n try {\n setAnswer(await posReadersCall<ReadersAnswer>(user, { action: 'list', hostId, refresh }))\n } catch {\n setAnswer(null)\n }\n },\n [user, hostId],\n )\n const uid = user?.uid ?? ''\n useEffect(() => {\n void load(true)\n // Keyed on the person, not the session object (see the register page).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [uid, hostId])\n\n const registerIds = registers.map((register: any) => register.$id).join(',')\n useEffect(() => {\n if (!user || !registerIds) return\n let active = true\n void Promise.all(\n registerIds.split(',').map(async (id) => {\n const result = await posDisplayCall<{ displays: DisplayRow[] }>(user, {\n action: 'displays',\n hostId,\n registerId: id,\n }).catch(() => ({ displays: [] as DisplayRow[] }))\n return [id, result.displays] as const\n }),\n ).then((entries) => {\n if (active) setDisplays(Object.fromEntries(entries))\n })\n return () => {\n active = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [uid, hostId, registerIds])\n\n const registerName = (id: string | null) =>\n registers.find((register: any) => register.$id === id)?.name ?? null\n\n const addReader = async () => {\n if (!user) return\n setBusy(true)\n try {\n await posReadersCall(user, {\n action: 'register',\n hostId,\n registrationCode: code.trim(),\n label: label.trim(),\n ...(registerId ? { registerId } : {}),\n ...(answer?.locationReady ? {} : { address }),\n })\n setAdding(false)\n setCode('')\n setLabel('')\n setRegisterId('')\n await load()\n } catch (error) {\n notify(error, 'The reader could not be added')\n } finally {\n setBusy(false)\n }\n }\n\n const readers = answer?.readers ?? []\n const showReaders = Boolean(answer?.available)\n\n /*\n * Arrived by a kiosk's \"Open POS devices\" (AGL-3982): this card renders\n * after the page has already tried to scroll to the anchor, so it brings\n * itself into view.\n */\n useEffect(() => {\n if (typeof window === 'undefined' || window.location.hash !== `#${POS_DEVICES_ANCHOR}`) return\n document.getElementById(POS_DEVICES_ANCHOR)?.scrollIntoView?.({ block: 'start' })\n }, [])\n\n return (\n <CardDisplay\n id={POS_DEVICES_ANCHOR}\n header={'POS devices'}\n help={pluginDocsHelp('pos', { anchor: '#card-readers' })}\n HeaderProps={\n showReaders || noRegisters\n ? {\n action: (\n <Stack direction=\"row\" spacing={1}>\n {noRegisters ? (\n <Button size=\"small\" href={`#${POS_REGISTERS_ANCHOR}`}>\n {'Add a register'}\n </Button>\n ) : null}\n {showReaders ? (\n <Button size=\"small\" onClick={() => setAdding(true)}>\n {'Add card reader'}\n </Button>\n ) : null}\n </Stack>\n ),\n }\n : undefined\n }\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {showReaders ? (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Card readers'}</Typography>\n {readers.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {answer?.testMode\n ? 'No card readers yet. In test mode, add one with the code \"simulated-wpe\" to try a simulated reader.'\n : 'No card readers yet. Add a Stripe Reader S700 or BBPOS WisePOS E with the code it shows on screen.'}\n </Typography>\n ) : (\n readers.map((reader) => (\n <Stack\n key={reader.id}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}\n >\n <Typography variant=\"body2\" sx={{ flex: 1, minWidth: 160 }}>\n {reader.label}\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {` · ${registerName(reader.registerId) ?? 'Any register'}` +\n (reader.livemode ? '' : ' · test')}\n </Typography>\n </Typography>\n <Chip\n size=\"small\"\n label={reader.status === 'online' ? 'Online' : 'Offline'}\n color={reader.status === 'online' ? 'success' : 'default'}\n />\n <TextField\n select\n size=\"small\"\n label=\"Register\"\n value={reader.registerId ?? ''}\n onChange={async (event) => {\n if (!user) return\n try {\n await posReadersCall(user, {\n action: 'update',\n hostId,\n readerId: reader.id,\n registerId: event.target.value,\n })\n await load()\n } catch (error) {\n notify(error, 'The reader could not be updated')\n }\n }}\n sx={{ minWidth: 140 }}\n >\n <MenuItem value=\"\">{'Any register'}</MenuItem>\n {registers.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n <Button\n size=\"small\"\n onClick={() => setRenaming({ id: reader.id, label: reader.label })}\n >\n {'Rename'}\n </Button>\n <Button\n size=\"small\"\n color=\"error\"\n onClick={async () => {\n const confirmed = await confirm({\n title: 'Remove this card reader?',\n description:\n `\"${reader.label}\" is removed from your account and stops taking payments. ` +\n 'To use it again, register it with a new code.',\n confirmationText: 'Remove',\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed || !user) return\n try {\n await posReadersCall(user, { action: 'remove', hostId, readerId: reader.id })\n await load()\n } catch (error) {\n notify(error, 'The reader could not be removed')\n }\n }}\n >\n {'Remove'}\n </Button>\n </Stack>\n ))\n )}\n </Stack>\n ) : null}\n {/* What the readers show while idle (AGL-4048); renders nothing\n where card readers are not offered. */}\n {showReaders ? <PosReaderSplashSetting hostId={hostId} canManagePos={canManagePos} /> : null}\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Customer displays and kiosks'}</Typography>\n {noRegisters ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'A display or kiosk pairs to a register. Add a register first.'}\n </Typography>\n ) : (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {pairBlocked ??\n 'Pair display gives you a code. Open the address it shows on the tablet and enter the code.'}\n </Typography>\n {registers.map((register: any) => (\n <Stack key={register.$id} spacing={0.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1, fontWeight: 'fontWeightMedium' }} noWrap>\n {register.name}\n </Typography>\n <Button\n size=\"small\"\n disabled={Boolean(pairBlocked)}\n onClick={() => void pairingFlow.open(register.$id, 'display', register.name)}\n aria-label={`Pair display to ${register.name}`}\n >\n {'Pair display'}\n </Button>\n </Stack>\n {(displays[register.$id] ?? []).map((display) => (\n <Stack key={`${register.$id}:${display.id}`} direction=\"row\" spacing={1} sx={{ alignItems: 'center', pl: 2 }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {display.label}\n </Typography>\n <Chip\n size=\"small\"\n label={Date.now() - display.lastSeenAtMs < 120_000 ? 'Connected' : 'Not connected'}\n color={Date.now() - display.lastSeenAtMs < 120_000 ? 'success' : 'default'}\n />\n <Button\n size=\"small\"\n color=\"error\"\n onClick={async () => {\n if (!user) return\n try {\n await posDisplayCall(user, {\n action: 'revoke',\n hostId,\n registerId: register.$id,\n displayId: display.id,\n })\n setDisplays((prev) => ({\n ...prev,\n [register.$id]: (prev[register.$id] ?? []).filter((entry) => entry.id !== display.id),\n }))\n } catch (error) {\n notify(error, 'The display could not be signed out')\n }\n }}\n >\n {'Sign out'}\n </Button>\n </Stack>\n ))}\n </Stack>\n ))}\n </>\n )}\n </Stack>\n </Stack>\n\n <Dialog open={Boolean(renaming)} onClose={() => setRenaming(null)} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Rename card reader'}</DialogTitle>\n <DialogContent>\n <TextField\n label=\"Name\"\n value={renaming?.label ?? ''}\n onChange={(event) => setRenaming((prev) => (prev ? { ...prev, label: event.target.value } : prev))}\n fullWidth\n autoFocus\n sx={{ mt: 1 }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setRenaming(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n disabled={!renaming?.label.trim()}\n onClick={async () => {\n if (!renaming || !user) return\n try {\n await posReadersCall(user, {\n action: 'update',\n hostId,\n readerId: renaming.id,\n label: renaming.label.trim(),\n })\n setRenaming(null)\n await load()\n } catch (error) {\n notify(error, 'The reader could not be renamed')\n }\n }}\n >\n {'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n <Dialog open={adding} onClose={() => setAdding(false)} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{'Add a card reader'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 1 }}>\n {'On the reader, open Settings and choose Generate pairing code, then enter the code it shows.'}\n </Typography>\n <TextField\n label=\"Registration code\"\n value={code}\n onChange={(event) => setCode(event.target.value)}\n autoFocus\n slotProps={{ htmlInput: { autoComplete: 'off' } }}\n />\n <TextField label=\"Name\" placeholder=\"Front counter reader\" value={label} onChange={(event) => setLabel(event.target.value)} />\n <TextField select label=\"Register\" value={registerId} onChange={(event) => setRegisterId(event.target.value)}>\n <MenuItem value=\"\">{'Any register'}</MenuItem>\n {registers.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n {answer && !answer.locationReady ? (\n <Box sx={{ display: 'grid', gap: 1.5, gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' } }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ gridColumn: '1 / -1' }}>\n {'Where the reader is used. Stripe sets the reader up for this country.'}\n </Typography>\n <TextField label=\"Street\" value={address.line1} onChange={(event) => setAddress({ ...address, line1: event.target.value })} sx={{ gridColumn: '1 / -1' }} />\n <TextField label=\"City\" value={address.city} onChange={(event) => setAddress({ ...address, city: event.target.value })} />\n <TextField label=\"State\" value={address.state} onChange={(event) => setAddress({ ...address, state: event.target.value })} />\n <TextField label=\"Postal code\" value={address.postalCode} onChange={(event) => setAddress({ ...address, postalCode: event.target.value })} />\n <TextField\n label=\"Country\"\n value={address.country}\n onChange={(event) => setAddress({ ...address, country: event.target.value.toUpperCase().slice(0, 2) })}\n />\n </Box>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setAdding(false)}>{'Cancel'}</Button>\n <Button variant=\"contained\" disabled={busy || !code.trim()} onClick={() => void addReader()}>\n {'Add reader'}\n </Button>\n </DialogActions>\n </Dialog>\n {pairingFlow.dialog}\n </CardDisplay>\n )\n}\nPosDevicesCard.displayName = 'PosDevicesCard'\n\nexport default PosDevicesCard\n"],"names":["Aglyn","pluginDocsHelp","CardDisplay","useConfirmationContext","useSnackbar","useFirestore","useFirestoreCollection","useOrgPlan","useUser","Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Typography","collection","limit","query","useCallback","useEffect","useState","posDisplayCall","posReadersCall","PosRequestError","POS_DEVICES_ANCHOR","POS_REGISTERS_ANCHOR","usePosPairing","PosReaderSplashSetting","EMPTY_ADDRESS","line1","line2","city","state","postalCode","country","PosDevicesCard","hostId","canManagePos","firestore","data","user","enqueueSnackbar","confirm","registerDocs","idField","noRegisters","undefined","length","registers","sort","a","b","String","name","localeCompare","answer","setAnswer","displays","setDisplays","adding","setAdding","code","setCode","label","setLabel","registerId","setRegisterId","address","setAddress","busy","setBusy","renaming","setRenaming","org","ready","planReady","posEntitled","checkEntitlement","notify","error","fallback","message","variant","persist","onPairingError","pairingFlow","onError","pairBlocked","load","refresh","action","uid","registerIds","map","register","$id","join","active","Promise","all","split","id","result","catch","then","entries","Object","fromEntries","registerName","find","addReader","registrationCode","trim","locationReady","readers","showReaders","Boolean","available","document","window","location","hash","getElementById","scrollIntoView","block","header","help","anchor","HeaderProps","direction","spacing","size","href","onClick","contentGutterX","contentGutterY","color","testMode","reader","sx","alignItems","flexWrap","rowGap","flex","minWidth","component","livemode","status","select","value","onChange","event","readerId","target","confirmed","title","description","confirmationText","confirmationButtonProps","fontWeight","noWrap","disabled","open","aria-label","display","pl","Date","now","lastSeenAtMs","displayId","prev","filter","entry","onClose","maxWidth","fullWidth","autoFocus","mt","flexDirection","gap","slotProps","htmlInput","autoComplete","placeholder","gridTemplateColumns","xs","sm","gridColumn","toUpperCase","slice","dialog","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-devices-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, useFirestoreCollection, useOrgPlan, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, limit, query } from 'firebase/firestore'\nimport { lazy, Suspense, useCallback, useEffect, useState } from 'react'\nimport type { PosCellularView } from '../../model/pos-cellular'\nimport { posDisplayCall, posReadersCall, PosRequestError } from './pos/pos-api'\nimport { POS_DEVICES_ANCHOR } from './pos/pos-kiosk-readiness.component'\nimport { POS_REGISTERS_ANCHOR, usePosPairing } from './pos/pos-pairing.component'\nimport { PosReaderSplashSetting } from './pos-reader-splash-setting.component'\n\ninterface ReaderRow {\n id: string\n label: string\n registerId: string | null\n deviceType: string | null\n serialNumber: string | null\n status: string\n livemode: boolean\n}\n\ninterface ReadersAnswer {\n available: boolean\n testMode: boolean\n locationReady: boolean\n /** 4G for the store's S710s, where it is offered and the store has one (AGL-4038). */\n cellular?: PosCellularView\n readers: ReaderRow[]\n}\n\n/** Drawn only where 4G is offered, so it arrives with the first store that shows it. */\nconst PosCellularControl = lazy(() => import('./pos-cellular-control.component'))\n\ninterface DisplayRow {\n id: string\n label: string\n createdAtMs: number\n lastSeenAtMs: number\n}\n\nexport interface PosDevicesCardProps {\n hostId: string\n /**\n * Whether the viewer may work this site's register: `managePos`, as the\n * shell resolved it, on a site role that may run it (admin or editor).\n * Pairing a tablet is refused by the server otherwise, so the card says why\n * rather than offering a button that fails. Absent reads as not allowed.\n */\n canManagePos?: boolean\n /**\n * Whether the viewer may set the register's devices up (AGL-4047): the\n * \"Registers and devices\" key on top of `canManagePos`. Adding, renaming,\n * moving and removing a reader, pairing a display and signing one out are\n * refused by the server without it, so each control says why. Absent\n * follows `canManagePos`.\n */\n canSetUpDevices?: boolean\n}\n\n/** Why a device control is not offered to someone who works the register. */\nconst DEVICES_KEY_REASON =\n 'Only a member with the \"Registers and devices\" permission can set up card readers, displays and kiosks.'\n\nconst EMPTY_ADDRESS = { line1: '', line2: '', city: '', state: '', postalCode: '', country: 'US' }\n\n/**\n * The register's hardware (AGL-3607, AGL-3608): Stripe Terminal card readers\n * — registered with the code a reader shows, bound to a register, renamed,\n * removed — and the customer displays paired to each register, which can be\n * signed out. Readers appear only where card readers are offered at all.\n *\n * Each register pairs a new customer display or self-service kiosk here,\n * through the same flow as the register's own Pair display (AGL-3712); a site\n * with no register is sent to the card that makes one.\n */\nexport function PosDevicesCard({\n hostId,\n canManagePos = false,\n canSetUpDevices = canManagePos,\n}: PosDevicesCardProps) {\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const { data: registerDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'registers'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n // Not \"no registers\" until the listen has answered.\n const noRegisters = registerDocs !== undefined && registerDocs.length === 0\n const registers = [...(registerDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n const [answer, setAnswer] = useState<ReadersAnswer | null>(null)\n const [displays, setDisplays] = useState<Record<string, DisplayRow[]>>({})\n const [adding, setAdding] = useState(false)\n const [code, setCode] = useState('')\n const [label, setLabel] = useState('')\n const [registerId, setRegisterId] = useState('')\n const [address, setAddress] = useState(EMPTY_ADDRESS)\n const [busy, setBusy] = useState(false)\n const [renaming, setRenaming] = useState<{ id: string; label: string } | null>(null)\n const { org, ready: planReady } = useOrgPlan(hostId)\n const posEntitled = planReady && Aglyn.checkEntitlement(org as any, 'pos')\n\n const notify = useCallback(\n (error: unknown, fallback: string) =>\n enqueueSnackbar(error instanceof PosRequestError ? error.message : fallback, {\n variant: 'warning',\n persist: false,\n }),\n [enqueueSnackbar],\n )\n\n const onPairingError = useCallback(\n (message: string) => enqueueSnackbar(message, { variant: 'warning', persist: false }),\n [enqueueSnackbar],\n )\n const pairingFlow = usePosPairing({ user, hostId, onError: onPairingError })\n /** Why pairing is not offered to this viewer, or null when it is. */\n const pairBlocked = !planReady\n ? 'Checking your plan…'\n : !posEntitled\n ? 'Point of Sale is not on your plan. Upgrade in Billing to pair displays and kiosks.'\n : !canManagePos\n ? 'Only an admin or editor with the \"Use the point of sale\" permission can pair displays and kiosks.'\n : !canSetUpDevices\n ? DEVICES_KEY_REASON\n : null\n /** Why the reader controls are not offered, or null when they are. */\n const readersBlocked = !canManagePos\n ? 'Only an admin or editor with the \"Use the point of sale\" permission can set up card readers.'\n : !canSetUpDevices\n ? DEVICES_KEY_REASON\n : null\n\n const load = useCallback(\n async (refresh = false) => {\n if (!user) return\n try {\n setAnswer(await posReadersCall<ReadersAnswer>(user, { action: 'list', hostId, refresh }))\n } catch {\n setAnswer(null)\n }\n },\n [user, hostId],\n )\n const uid = user?.uid ?? ''\n useEffect(() => {\n void load(true)\n // Keyed on the person, not the session object (see the register page).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [uid, hostId])\n\n const registerIds = registers.map((register: any) => register.$id).join(',')\n useEffect(() => {\n if (!user || !registerIds) return\n let active = true\n void Promise.all(\n registerIds.split(',').map(async (id) => {\n const result = await posDisplayCall<{ displays: DisplayRow[] }>(user, {\n action: 'displays',\n hostId,\n registerId: id,\n }).catch(() => ({ displays: [] as DisplayRow[] }))\n return [id, result.displays] as const\n }),\n ).then((entries) => {\n if (active) setDisplays(Object.fromEntries(entries))\n })\n return () => {\n active = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [uid, hostId, registerIds])\n\n const registerName = (id: string | null) =>\n registers.find((register: any) => register.$id === id)?.name ?? null\n\n const addReader = async () => {\n if (!user) return\n setBusy(true)\n try {\n await posReadersCall(user, {\n action: 'register',\n hostId,\n registrationCode: code.trim(),\n label: label.trim(),\n ...(registerId ? { registerId } : {}),\n ...(answer?.locationReady ? {} : { address }),\n })\n setAdding(false)\n setCode('')\n setLabel('')\n setRegisterId('')\n await load()\n } catch (error) {\n notify(error, 'The reader could not be added')\n } finally {\n setBusy(false)\n }\n }\n\n const readers = answer?.readers ?? []\n const showReaders = Boolean(answer?.available)\n\n /*\n * Arrived by a kiosk's \"Open POS devices\" (AGL-3982): this card renders\n * after the page has already tried to scroll to the anchor, so it brings\n * itself into view.\n */\n useEffect(() => {\n if (typeof window === 'undefined' || window.location.hash !== `#${POS_DEVICES_ANCHOR}`) return\n document.getElementById(POS_DEVICES_ANCHOR)?.scrollIntoView?.({ block: 'start' })\n }, [])\n\n return (\n <CardDisplay\n id={POS_DEVICES_ANCHOR}\n header={'POS devices'}\n help={pluginDocsHelp('pos', { anchor: '#card-readers' })}\n HeaderProps={\n showReaders || noRegisters\n ? {\n action: (\n <Stack direction=\"row\" spacing={1}>\n {noRegisters ? (\n <Button size=\"small\" href={`#${POS_REGISTERS_ANCHOR}`}>\n {'Add a register'}\n </Button>\n ) : null}\n {showReaders ? (\n <BlockedControl blocked={Boolean(readersBlocked)} reason={readersBlocked ?? ''}>\n <Button size=\"small\" onClick={() => setAdding(true)}>\n {'Add card reader'}\n </Button>\n </BlockedControl>\n ) : null}\n </Stack>\n ),\n }\n : undefined\n }\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {showReaders ? (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Card readers'}</Typography>\n {readers.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {answer?.testMode\n ? 'No card readers yet. In test mode, add one with the code \"simulated-wpe\" to try a simulated reader.'\n : 'No card readers yet. Add a Stripe Reader S700 or BBPOS WisePOS E with the code it shows on screen.'}\n </Typography>\n ) : (\n readers.map((reader) => (\n <Stack\n key={reader.id}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 1 }}\n >\n <Typography variant=\"body2\" sx={{ flex: 1, minWidth: 160 }}>\n {reader.label}\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {` · ${registerName(reader.registerId) ?? 'Any register'}` +\n (reader.livemode ? '' : ' · test')}\n </Typography>\n </Typography>\n <Chip\n size=\"small\"\n label={reader.status === 'online' ? 'Online' : 'Offline'}\n color={reader.status === 'online' ? 'success' : 'default'}\n />\n <TextField\n select\n size=\"small\"\n label=\"Register\"\n disabled={Boolean(readersBlocked)}\n value={reader.registerId ?? ''}\n onChange={async (event) => {\n if (!user) return\n try {\n await posReadersCall(user, {\n action: 'update',\n hostId,\n readerId: reader.id,\n registerId: event.target.value,\n })\n await load()\n } catch (error) {\n notify(error, 'The reader could not be updated')\n }\n }}\n sx={{ minWidth: 140 }}\n >\n <MenuItem value=\"\">{'Any register'}</MenuItem>\n {registers.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n <BlockedControl blocked={Boolean(readersBlocked)} reason={readersBlocked ?? ''}>\n <Button\n size=\"small\"\n onClick={() => setRenaming({ id: reader.id, label: reader.label })}\n >\n {'Rename'}\n </Button>\n </BlockedControl>\n <Button\n size=\"small\"\n color=\"error\"\n disabled={Boolean(readersBlocked)}\n title={readersBlocked ?? undefined}\n onClick={async () => {\n const confirmed = await confirm({\n title: 'Remove this card reader?',\n description:\n `\"${reader.label}\" is removed from your account and stops taking payments. ` +\n 'To use it again, register it with a new code.',\n confirmationText: 'Remove',\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed || !user) return\n try {\n await posReadersCall(user, { action: 'remove', hostId, readerId: reader.id })\n await load()\n } catch (error) {\n notify(error, 'The reader could not be removed')\n }\n }}\n >\n {'Remove'}\n </Button>\n </Stack>\n ))\n )}\n </Stack>\n ) : null}\n {showReaders && answer?.cellular ? (\n <Suspense fallback={null}>\n <PosCellularControl\n hostId={hostId}\n cellular={answer.cellular}\n blocked={readersBlocked}\n onChanged={() => load()}\n />\n </Suspense>\n ) : null}\n {/* What the readers show while idle (AGL-4048); renders nothing\n where card readers are not offered. */}\n {showReaders ? (\n <PosReaderSplashSetting hostId={hostId} canManagePos={canManagePos && canSetUpDevices} />\n ) : null}\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Customer displays and kiosks'}</Typography>\n {noRegisters ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'A display or kiosk pairs to a register. Add a register first.'}\n </Typography>\n ) : (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {pairBlocked ??\n 'Pair display gives you a code. Open the address it shows on the tablet and enter the code.'}\n </Typography>\n {registers.map((register: any) => (\n <Stack key={register.$id} spacing={0.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1, fontWeight: 'fontWeightMedium' }} noWrap>\n {register.name}\n </Typography>\n <Button\n size=\"small\"\n disabled={Boolean(pairBlocked)}\n onClick={() => void pairingFlow.open(register.$id, 'display', register.name)}\n aria-label={`Pair display to ${register.name}`}\n >\n {'Pair display'}\n </Button>\n </Stack>\n {(displays[register.$id] ?? []).map((display) => (\n <Stack key={`${register.$id}:${display.id}`} direction=\"row\" spacing={1} sx={{ alignItems: 'center', pl: 2 }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {display.label}\n </Typography>\n <Chip\n size=\"small\"\n label={Date.now() - display.lastSeenAtMs < 120_000 ? 'Connected' : 'Not connected'}\n color={Date.now() - display.lastSeenAtMs < 120_000 ? 'success' : 'default'}\n />\n <Button\n size=\"small\"\n color=\"error\"\n disabled={Boolean(pairBlocked)}\n title={pairBlocked ?? undefined}\n onClick={async () => {\n if (!user) return\n try {\n await posDisplayCall(user, {\n action: 'revoke',\n hostId,\n registerId: register.$id,\n displayId: display.id,\n })\n setDisplays((prev) => ({\n ...prev,\n [register.$id]: (prev[register.$id] ?? []).filter((entry) => entry.id !== display.id),\n }))\n } catch (error) {\n notify(error, 'The display could not be signed out')\n }\n }}\n >\n {'Sign out'}\n </Button>\n </Stack>\n ))}\n </Stack>\n ))}\n </>\n )}\n </Stack>\n </Stack>\n\n <Dialog open={Boolean(renaming)} onClose={() => setRenaming(null)} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Rename card reader'}</DialogTitle>\n <DialogContent>\n <TextField\n label=\"Name\"\n value={renaming?.label ?? ''}\n onChange={(event) => setRenaming((prev) => (prev ? { ...prev, label: event.target.value } : prev))}\n fullWidth\n autoFocus\n sx={{ mt: 1 }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setRenaming(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n disabled={!renaming?.label.trim()}\n onClick={async () => {\n if (!renaming || !user) return\n try {\n await posReadersCall(user, {\n action: 'update',\n hostId,\n readerId: renaming.id,\n label: renaming.label.trim(),\n })\n setRenaming(null)\n await load()\n } catch (error) {\n notify(error, 'The reader could not be renamed')\n }\n }}\n >\n {'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n <Dialog open={adding} onClose={() => setAdding(false)} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{'Add a card reader'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 1 }}>\n {'On the reader, open Settings and choose Generate pairing code, then enter the code it shows.'}\n </Typography>\n {answer?.cellular?.enabled ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'4G is on at this store: a Stripe Reader S710 you add gets it too, and is charged for it each month.'}\n </Typography>\n ) : null}\n <TextField\n label=\"Registration code\"\n value={code}\n onChange={(event) => setCode(event.target.value)}\n autoFocus\n slotProps={{ htmlInput: { autoComplete: 'off' } }}\n />\n <TextField label=\"Name\" placeholder=\"Front counter reader\" value={label} onChange={(event) => setLabel(event.target.value)} />\n <TextField select label=\"Register\" value={registerId} onChange={(event) => setRegisterId(event.target.value)}>\n <MenuItem value=\"\">{'Any register'}</MenuItem>\n {registers.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n {answer && !answer.locationReady ? (\n <Box sx={{ display: 'grid', gap: 1.5, gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' } }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ gridColumn: '1 / -1' }}>\n {'Where the reader is used. Stripe sets the reader up for this country.'}\n </Typography>\n <TextField label=\"Street\" value={address.line1} onChange={(event) => setAddress({ ...address, line1: event.target.value })} sx={{ gridColumn: '1 / -1' }} />\n <TextField label=\"City\" value={address.city} onChange={(event) => setAddress({ ...address, city: event.target.value })} />\n <TextField label=\"State\" value={address.state} onChange={(event) => setAddress({ ...address, state: event.target.value })} />\n <TextField label=\"Postal code\" value={address.postalCode} onChange={(event) => setAddress({ ...address, postalCode: event.target.value })} />\n <TextField\n label=\"Country\"\n value={address.country}\n onChange={(event) => setAddress({ ...address, country: event.target.value.toUpperCase().slice(0, 2) })}\n />\n </Box>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setAdding(false)}>{'Cancel'}</Button>\n <Button variant=\"contained\" disabled={busy || !code.trim()} onClick={() => void addReader()}>\n {'Add reader'}\n </Button>\n </DialogActions>\n </Dialog>\n {pairingFlow.dialog}\n </CardDisplay>\n )\n}\nPosDevicesCard.displayName = 'PosDevicesCard'\n\nexport default PosDevicesCard\n"],"names":["Aglyn","pluginDocsHelp","CardDisplay","useConfirmationContext","BlockedControl","useSnackbar","useFirestore","useFirestoreCollection","useOrgPlan","useUser","Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Typography","collection","limit","query","lazy","Suspense","useCallback","useEffect","useState","posDisplayCall","posReadersCall","PosRequestError","POS_DEVICES_ANCHOR","POS_REGISTERS_ANCHOR","usePosPairing","PosReaderSplashSetting","PosCellularControl","DEVICES_KEY_REASON","EMPTY_ADDRESS","line1","line2","city","state","postalCode","country","PosDevicesCard","hostId","canManagePos","canSetUpDevices","answer","firestore","data","user","enqueueSnackbar","confirm","registerDocs","idField","noRegisters","undefined","length","registers","sort","a","b","String","name","localeCompare","setAnswer","displays","setDisplays","adding","setAdding","code","setCode","label","setLabel","registerId","setRegisterId","address","setAddress","busy","setBusy","renaming","setRenaming","org","ready","planReady","posEntitled","checkEntitlement","notify","error","fallback","message","variant","persist","onPairingError","pairingFlow","onError","pairBlocked","readersBlocked","load","refresh","action","uid","registerIds","map","register","$id","join","active","Promise","all","split","id","result","catch","then","entries","Object","fromEntries","registerName","find","addReader","registrationCode","trim","locationReady","readers","showReaders","Boolean","available","document","window","location","hash","getElementById","scrollIntoView","block","header","help","anchor","HeaderProps","direction","spacing","size","href","blocked","reason","onClick","contentGutterX","contentGutterY","color","testMode","reader","sx","alignItems","flexWrap","rowGap","flex","minWidth","component","livemode","status","select","disabled","value","onChange","event","readerId","target","title","confirmed","description","confirmationText","confirmationButtonProps","cellular","onChanged","fontWeight","noWrap","open","aria-label","display","pl","Date","now","lastSeenAtMs","displayId","prev","filter","entry","onClose","maxWidth","fullWidth","autoFocus","mt","flexDirection","gap","enabled","slotProps","htmlInput","autoComplete","placeholder","gridTemplateColumns","xs","sm","gridColumn","toUpperCase","slice","dialog","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AACrC,SAASC,cAAc,QAAQ,eAAc;AAC7C,SAASC,WAAW,EAAEC,sBAAsB,QAAQ,uBAAsB;AAC1E,SAASC,cAAc,QAAQ,4DAA2D;AAC1F,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,YAAY,EAAEC,sBAAsB,EAAEC,UAAU,EAAEC,OAAO,QAAQ,iCAAgC;AAC1G,SACEC,GAAG,EACHC,MAAM,EACNC,IAAI,EACJC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,UAAU,QACL,gBAAe;AACtB,SAASC,UAAU,EAAEC,KAAK,EAAEC,KAAK,QAAQ,qBAAoB;AAC7D,SAASC,IAAI,EAAEC,QAAQ,EAAEC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAExE,SAASC,cAAc,EAAEC,cAAc,EAAEC,eAAe,QAAQ,mBAAe;AAC/E,SAASC,kBAAkB,QAAQ,yCAAqC;AACxE,SAASC,oBAAoB,EAAEC,aAAa,QAAQ,iCAA6B;AACjF,SAASC,sBAAsB,QAAQ,2CAAuC;AAqB9E,sFAAsF,GACtF,MAAMC,mCAAqBZ,KAAK,IAAM,MAAM,CAAC;AA4B7C,2EAA2E,GAC3E,MAAMa,qBACJ;AAEF,MAAMC,gBAAgB;IAAEC,OAAO;IAAIC,OAAO;IAAIC,MAAM;IAAIC,OAAO;IAAIC,YAAY;IAAIC,SAAS;AAAK;AAEjG;;;;;;;;;CASC,GACD,OAAO,SAASC,eAAe,EAC7BC,MAAM,EACNC,eAAe,KAAK,EACpBC,kBAAkBD,YAAY,EACV;;QA4YXE;IA3YT,MAAMC,YAAY5C;IAClB,MAAM,EAAE6C,MAAMC,IAAI,EAAE,GAAG3C;IACvB,MAAM,EAAE4C,eAAe,EAAE,GAAGhD;IAC5B,MAAM,EAAEiD,OAAO,EAAE,GAAGnD;IACpB,MAAM,EAAEgD,MAAMI,YAAY,EAAE,GAAGhD,uBAC7B,IAAMgB,MAAMF,WAAW6B,WAAW,SAASJ,QAAQ,cAAcxB,MAAM,MACvE;QAAC4B;QAAWJ;KAAO,EACnB;QAAEU,SAAS;IAAM;IAEnB,oDAAoD;IACpD,MAAMC,cAAcF,iBAAiBG,aAAaH,aAAaI,MAAM,KAAK;IAC1E,MAAMC,YAAY;WAAKL,uBAAAA,eAAgB,EAAE;KAAE,CAACM,IAAI,CAAC,CAACC,GAAQC;YACjDD,SAAmCC;eAA1CC,QAAOF,UAAAA,EAAEG,IAAI,YAANH,UAAU,IAAII,aAAa,CAACF,QAAOD,UAAAA,EAAEE,IAAI,YAANF,UAAU;;IAEtD,MAAM,CAACd,QAAQkB,UAAU,GAAGvC,SAA+B;IAC3D,MAAM,CAACwC,UAAUC,YAAY,GAAGzC,SAAuC,CAAC;IACxE,MAAM,CAAC0C,QAAQC,UAAU,GAAG3C,SAAS;IACrC,MAAM,CAAC4C,MAAMC,QAAQ,GAAG7C,SAAS;IACjC,MAAM,CAAC8C,OAAOC,SAAS,GAAG/C,SAAS;IACnC,MAAM,CAACgD,YAAYC,cAAc,GAAGjD,SAAS;IAC7C,MAAM,CAACkD,SAASC,WAAW,GAAGnD,SAASU;IACvC,MAAM,CAAC0C,MAAMC,QAAQ,GAAGrD,SAAS;IACjC,MAAM,CAACsD,UAAUC,YAAY,GAAGvD,SAA+C;IAC/E,MAAM,EAAEwD,GAAG,EAAEC,OAAOC,SAAS,EAAE,GAAG9E,WAAWsC;IAC7C,MAAMyC,cAAcD,aAAatF,MAAMwF,gBAAgB,CAACJ,KAAY;IAEpE,MAAMK,SAAS/D,YACb,CAACgE,OAAgBC,WACftC,gBAAgBqC,iBAAiB3D,kBAAkB2D,MAAME,OAAO,GAAGD,UAAU;YAC3EE,SAAS;YACTC,SAAS;QACX,IACF;QAACzC;KAAgB;IAGnB,MAAM0C,iBAAiBrE,YACrB,CAACkE,UAAoBvC,gBAAgBuC,SAAS;YAAEC,SAAS;YAAWC,SAAS;QAAM,IACnF;QAACzC;KAAgB;IAEnB,MAAM2C,cAAc9D,cAAc;QAAEkB;QAAMN;QAAQmD,SAASF;IAAe;IAC1E,mEAAmE,GACnE,MAAMG,cAAc,CAACZ,YACjB,wBACA,CAACC,cACC,uFACA,CAACxC,eACC,sGACA,CAACC,kBACCX,qBACA;IACV,oEAAoE,GACpE,MAAM8D,iBAAiB,CAACpD,eACpB,iGACA,CAACC,kBACCX,qBACA;IAEN,MAAM+D,OAAO1E,YACX,OAAO2E,UAAU,KAAK;QACpB,IAAI,CAACjD,MAAM;QACX,IAAI;YACFe,UAAU,MAAMrC,eAA8BsB,MAAM;gBAAEkD,QAAQ;gBAAQxD;gBAAQuD;YAAQ;QACxF,EAAE,eAAM;YACNlC,UAAU;QACZ;IACF,GACA;QAACf;QAAMN;KAAO;IAEhB,MAAMyD,cAAMnD,wBAAAA,KAAMmD,GAAG,mBAAI;IACzB5E,UAAU;QACR,KAAKyE,KAAK;IACV,uEAAuE;IACvE,uDAAuD;IACzD,GAAG;QAACG;QAAKzD;KAAO;IAEhB,MAAM0D,cAAc5C,UAAU6C,GAAG,CAAC,CAACC,WAAkBA,SAASC,GAAG,EAAEC,IAAI,CAAC;IACxEjF,UAAU;QACR,IAAI,CAACyB,QAAQ,CAACoD,aAAa;QAC3B,IAAIK,SAAS;QACb,KAAKC,QAAQC,GAAG,CACdP,YAAYQ,KAAK,CAAC,KAAKP,GAAG,CAAC,OAAOQ;YAChC,MAAMC,SAAS,MAAMrF,eAA2CuB,MAAM;gBACpEkD,QAAQ;gBACRxD;gBACA8B,YAAYqC;YACd,GAAGE,KAAK,CAAC,IAAO,CAAA;oBAAE/C,UAAU,EAAE;gBAAiB,CAAA;YAC/C,OAAO;gBAAC6C;gBAAIC,OAAO9C,QAAQ;aAAC;QAC9B,IACAgD,IAAI,CAAC,CAACC;YACN,IAAIR,QAAQxC,YAAYiD,OAAOC,WAAW,CAACF;QAC7C;QACA,OAAO;YACLR,SAAS;QACX;IACA,uDAAuD;IACzD,GAAG;QAACN;QAAKzD;QAAQ0D;KAAY;IAE7B,MAAMgB,eAAe,CAACP;;YACpBrD;wBAAAA,kBAAAA,UAAU6D,IAAI,CAAC,CAACf,WAAkBA,SAASC,GAAG,KAAKM,wBAAnDrD,gBAAwDK,IAAI,mBAAI;;IAElE,MAAMyD,YAAY;QAChB,IAAI,CAACtE,MAAM;QACX6B,QAAQ;QACR,IAAI;YACF,MAAMnD,eAAesB,MAAM;gBACzBkD,QAAQ;gBACRxD;gBACA6E,kBAAkBnD,KAAKoD,IAAI;gBAC3BlD,OAAOA,MAAMkD,IAAI;eACbhD,aAAa;gBAAEA;YAAW,IAAI,CAAC,GAC/B3B,CAAAA,0BAAAA,OAAQ4E,aAAa,IAAG,CAAC,IAAI;gBAAE/C;YAAQ;YAE7CP,UAAU;YACVE,QAAQ;YACRE,SAAS;YACTE,cAAc;YACd,MAAMuB;QACR,EAAE,OAAOV,OAAO;YACdD,OAAOC,OAAO;QAChB,SAAU;YACRT,QAAQ;QACV;IACF;IAEA,MAAM6C,mBAAU7E,0BAAAA,OAAQ6E,OAAO,oBAAI,EAAE;IACrC,MAAMC,cAAcC,QAAQ/E,0BAAAA,OAAQgF,SAAS;IAE7C;;;;GAIC,GACDtG,UAAU;YAERuG,yCAAAA;QADA,IAAI,OAAOC,WAAW,eAAeA,OAAOC,QAAQ,CAACC,IAAI,KAAK,CAAC,CAAC,EAAErG,oBAAoB,EAAE;SACxFkG,2BAAAA,SAASI,cAAc,CAACtG,yCAAxBkG,0CAAAA,yBAA6CK,cAAc,qBAA3DL,6CAAAA,0BAA8D;YAAEM,OAAO;QAAQ;IACjF,GAAG,EAAE;IAEL,qBACE,MAACtI;QACC+G,IAAIjF;QACJyG,QAAQ;QACRC,MAAMzI,eAAe,OAAO;YAAE0I,QAAQ;QAAgB;QACtDC,aACEb,eAAetE,cACX;YACE6C,sBACE,MAACpF;gBAAM2H,WAAU;gBAAMC,SAAS;;oBAC7BrF,4BACC,KAAC9C;wBAAOoI,MAAK;wBAAQC,MAAM,CAAC,CAAC,EAAE/G,sBAAsB;kCAClD;yBAED;oBACH8F,4BACC,KAAC3H;wBAAe6I,SAASjB,QAAQ7B;wBAAiB+C,MAAM,EAAE/C,yBAAAA,iBAAkB;kCAC1E,cAAA,KAACxF;4BAAOoI,MAAK;4BAAQI,SAAS,IAAM5E,UAAU;sCAC3C;;yBAGH;;;QAGV,IACAb;QAEN0F,cAAc;QACdC,cAAc;;0BAEd,MAACnI;gBAAM4H,SAAS;;oBACbf,4BACC,MAAC7G;wBAAM4H,SAAS;;0CACd,KAAC1H;gCAAWyE,SAAQ;0CAAa;;4BAChCiC,QAAQnE,MAAM,KAAK,kBAClB,KAACvC;gCAAWyE,SAAQ;gCAAQyD,OAAM;0CAC/BrG,CAAAA,0BAAAA,OAAQsG,QAAQ,IACb,wGACA;iCAGNzB,QAAQrB,GAAG,CAAC,CAAC+C;oCAUEhC,eAcFgC;qDAvBX,MAACtI;oCAEC2H,WAAU;oCACVC,SAAS;oCACTW,IAAI;wCAAEC,YAAY;wCAAUC,UAAU;wCAAQC,QAAQ;oCAAE;;sDAExD,MAACxI;4CAAWyE,SAAQ;4CAAQ4D,IAAI;gDAAEI,MAAM;gDAAGC,UAAU;4CAAI;;gDACtDN,OAAO9E,KAAK;8DACb,KAACtD;oDAAW2I,WAAU;oDAAOlE,SAAQ;oDAAUyD,OAAM;8DAClD,CAAC,GAAG,GAAE9B,gBAAAA,aAAagC,OAAO5E,UAAU,aAA9B4C,gBAAmC,gBAAgB,GACvDgC,CAAAA,OAAOQ,QAAQ,GAAG,KAAK,SAAQ;;;;sDAGtC,KAACpJ;4CACCmI,MAAK;4CACLrE,OAAO8E,OAAOS,MAAM,KAAK,WAAW,WAAW;4CAC/CX,OAAOE,OAAOS,MAAM,KAAK,WAAW,YAAY;;sDAElD,MAAC9I;4CACC+I,MAAM;4CACNnB,MAAK;4CACLrE,OAAM;4CACNyF,UAAUnC,QAAQ7B;4CAClBiE,KAAK,GAAEZ,qBAAAA,OAAO5E,UAAU,YAAjB4E,qBAAqB;4CAC5Ba,UAAU,OAAOC;gDACf,IAAI,CAAClH,MAAM;gDACX,IAAI;oDACF,MAAMtB,eAAesB,MAAM;wDACzBkD,QAAQ;wDACRxD;wDACAyH,UAAUf,OAAOvC,EAAE;wDACnBrC,YAAY0F,MAAME,MAAM,CAACJ,KAAK;oDAChC;oDACA,MAAMhE;gDACR,EAAE,OAAOV,OAAO;oDACdD,OAAOC,OAAO;gDAChB;4CACF;4CACA+D,IAAI;gDAAEK,UAAU;4CAAI;;8DAEpB,KAAC7I;oDAASmJ,OAAM;8DAAI;;gDACnBxG,UAAU6C,GAAG,CAAC,CAACC,yBACd,KAACzF;wDAA4BmJ,OAAO1D,SAASC,GAAG;kEAC7CD,SAASzC,IAAI;uDADDyC,SAASC,GAAG;;;sDAK/B,KAACvG;4CAAe6I,SAASjB,QAAQ7B;4CAAiB+C,MAAM,EAAE/C,yBAAAA,iBAAkB;sDAC1E,cAAA,KAACxF;gDACCoI,MAAK;gDACLI,SAAS,IAAMhE,YAAY;wDAAE8B,IAAIuC,OAAOvC,EAAE;wDAAEvC,OAAO8E,OAAO9E,KAAK;oDAAC;0DAE/D;;;sDAGL,KAAC/D;4CACCoI,MAAK;4CACLO,OAAM;4CACNa,UAAUnC,QAAQ7B;4CAClBsE,KAAK,EAAEtE,yBAAAA,iBAAkBzC;4CACzByF,SAAS;gDACP,MAAMuB,YAAY,MAAMpH,QAAQ;oDAC9BmH,OAAO;oDACPE,aACE,CAAC,CAAC,EAAEnB,OAAO9E,KAAK,CAAC,0DAA0D,CAAC,GAC5E;oDACFkG,kBAAkB;oDAClBC,yBAAyB;wDAAEvB,OAAO;oDAAQ;gDAC5C,GACGlC,IAAI,CAAC,IAAM,MACXD,KAAK,CAAC,IAAM;gDACf,IAAI,CAACuD,aAAa,CAACtH,MAAM;gDACzB,IAAI;oDACF,MAAMtB,eAAesB,MAAM;wDAAEkD,QAAQ;wDAAUxD;wDAAQyH,UAAUf,OAAOvC,EAAE;oDAAC;oDAC3E,MAAMb;gDACR,EAAE,OAAOV,OAAO;oDACdD,OAAOC,OAAO;gDAChB;4CACF;sDAEC;;;mCA/EE8D,OAAOvC,EAAE;;;yBAqFpB;oBACHc,gBAAe9E,0BAAAA,OAAQ6H,QAAQ,kBAC9B,KAACrJ;wBAASkE,UAAU;kCAClB,cAAA,KAACvD;4BACCU,QAAQA;4BACRgI,UAAU7H,OAAO6H,QAAQ;4BACzB7B,SAAS9C;4BACT4E,WAAW,IAAM3E;;yBAGnB;oBAGH2B,4BACC,KAAC5F;wBAAuBW,QAAQA;wBAAQC,cAAcA,gBAAgBC;yBACpE;kCACJ,MAAC9B;wBAAM4H,SAAS;;0CACd,KAAC1H;gCAAWyE,SAAQ;0CAAa;;4BAChCpC,4BACC,KAACrC;gCAAWyE,SAAQ;gCAAQyD,OAAM;0CAC/B;+CAGH;;kDACE,KAAClI;wCAAWyE,SAAQ;wCAAQyD,OAAM;kDAC/BpD,sBAAAA,cACC;;oCAEHtC,UAAU6C,GAAG,CAAC,CAACC;4CAeVtC;6DAdJ,MAAClD;4CAAyB4H,SAAS;;8DACjC,MAAC5H;oDAAM2H,WAAU;oDAAMC,SAAS;oDAAGW,IAAI;wDAAEC,YAAY;oDAAS;;sEAC5D,KAACtI;4DAAWyE,SAAQ;4DAAQ4D,IAAI;gEAAEI,MAAM;gEAAGmB,YAAY;4DAAmB;4DAAGC,MAAM;sEAChFvE,SAASzC,IAAI;;sEAEhB,KAACtD;4DACCoI,MAAK;4DACLoB,UAAUnC,QAAQ9B;4DAClBiD,SAAS,IAAM,KAAKnD,YAAYkF,IAAI,CAACxE,SAASC,GAAG,EAAE,WAAWD,SAASzC,IAAI;4DAC3EkH,cAAY,CAAC,gBAAgB,EAAEzE,SAASzC,IAAI,EAAE;sEAE7C;;;;gDAGJ,EAACG,yBAAAA,QAAQ,CAACsC,SAASC,GAAG,CAAC,YAAtBvC,yBAA0B,EAAE,EAAEqC,GAAG,CAAC,CAAC2E,wBACnC,MAAClK;wDAA4C2H,WAAU;wDAAMC,SAAS;wDAAGW,IAAI;4DAAEC,YAAY;4DAAU2B,IAAI;wDAAE;;0EACzG,KAACjK;gEAAWyE,SAAQ;gEAAQ4D,IAAI;oEAAEI,MAAM;gEAAE;0EACvCuB,QAAQ1G,KAAK;;0EAEhB,KAAC9D;gEACCmI,MAAK;gEACLrE,OAAO4G,KAAKC,GAAG,KAAKH,QAAQI,YAAY,GAAG,SAAU,cAAc;gEACnElC,OAAOgC,KAAKC,GAAG,KAAKH,QAAQI,YAAY,GAAG,SAAU,YAAY;;0EAEnE,KAAC7K;gEACCoI,MAAK;gEACLO,OAAM;gEACNa,UAAUnC,QAAQ9B;gEAClBuE,KAAK,EAAEvE,sBAAAA,cAAexC;gEACtByF,SAAS;oEACP,IAAI,CAAC/F,MAAM;oEACX,IAAI;wEACF,MAAMvB,eAAeuB,MAAM;4EACzBkD,QAAQ;4EACRxD;4EACA8B,YAAY8B,SAASC,GAAG;4EACxB8E,WAAWL,QAAQnE,EAAE;wEACvB;wEACA5C,YAAY,CAACqH;gFAEMA;mFAFI,aAClBA;gFACH,CAAChF,SAASC,GAAG,CAAC,EAAE,EAAC+E,qBAAAA,IAAI,CAAChF,SAASC,GAAG,CAAC,YAAlB+E,qBAAsB,EAAE,EAAEC,MAAM,CAAC,CAACC,QAAUA,MAAM3E,EAAE,KAAKmE,QAAQnE,EAAE;;;oEAExF,EAAE,OAAOvB,OAAO;wEACdD,OAAOC,OAAO;oEAChB;gEACF;0EAEC;;;uDAhCO,GAAGgB,SAASC,GAAG,CAAC,CAAC,EAAEyE,QAAQnE,EAAE,EAAE;;2CAfnCP,SAASC,GAAG;;;;;;;;0BA0DlC,MAAC9F;gBAAOqK,MAAMlD,QAAQ9C;gBAAW2G,SAAS,IAAM1G,YAAY;gBAAO2G,UAAS;gBAAKC,SAAS;;kCACxF,KAAC/K;kCAAa;;kCACd,KAACD;kCACC,cAAA,KAACI;4BACCuD,OAAM;4BACN0F,KAAK,WAAElF,4BAAAA,SAAUR,KAAK,oBAAI;4BAC1B2F,UAAU,CAACC,QAAUnF,YAAY,CAACuG,OAAUA,OAAO,aAAKA;wCAAMhH,OAAO4F,MAAME,MAAM,CAACJ,KAAK;yCAAKsB;4BAC5FK,SAAS;4BACTC,SAAS;4BACTvC,IAAI;gCAAEwC,IAAI;4BAAE;;;kCAGhB,MAACnL;;0CACC,KAACH;gCAAOwI,SAAS,IAAMhE,YAAY;0CAAQ;;0CAC3C,KAACxE;gCACCkF,SAAQ;gCACRsE,UAAU,EAACjF,4BAAAA,SAAUR,KAAK,CAACkD,IAAI;gCAC/BuB,SAAS;oCACP,IAAI,CAACjE,YAAY,CAAC9B,MAAM;oCACxB,IAAI;wCACF,MAAMtB,eAAesB,MAAM;4CACzBkD,QAAQ;4CACRxD;4CACAyH,UAAUrF,SAAS+B,EAAE;4CACrBvC,OAAOQ,SAASR,KAAK,CAACkD,IAAI;wCAC5B;wCACAzC,YAAY;wCACZ,MAAMiB;oCACR,EAAE,OAAOV,OAAO;wCACdD,OAAOC,OAAO;oCAChB;gCACF;0CAEC;;;;;;0BAIP,MAAC7E;gBAAOqK,MAAM5G;gBAAQuH,SAAS,IAAMtH,UAAU;gBAAQuH,UAAS;gBAAKC,SAAS;;kCAC5E,KAAC/K;kCAAa;;kCACd,MAACD;wBAAc0I,IAAI;4BAAE2B,SAAS;4BAAQc,eAAe;4BAAUC,KAAK;wBAAE;;0CACpE,KAAC/K;gCAAWyE,SAAQ;gCAAQyD,OAAM;gCAAiBG,IAAI;oCAAEwC,IAAI;gCAAE;0CAC5D;;4BAEFhJ,CAAAA,2BAAAA,mBAAAA,OAAQ6H,QAAQ,qBAAhB7H,iBAAkBmJ,OAAO,kBACxB,KAAChL;gCAAWyE,SAAQ;gCAAQyD,OAAM;0CAC/B;iCAED;0CACJ,KAACnI;gCACCuD,OAAM;gCACN0F,OAAO5F;gCACP6F,UAAU,CAACC,QAAU7F,QAAQ6F,MAAME,MAAM,CAACJ,KAAK;gCAC/C4B,SAAS;gCACTK,WAAW;oCAAEC,WAAW;wCAAEC,cAAc;oCAAM;gCAAE;;0CAElD,KAACpL;gCAAUuD,OAAM;gCAAO8H,aAAY;gCAAuBpC,OAAO1F;gCAAO2F,UAAU,CAACC,QAAU3F,SAAS2F,MAAME,MAAM,CAACJ,KAAK;;0CACzH,MAACjJ;gCAAU+I,MAAM;gCAACxF,OAAM;gCAAW0F,OAAOxF;gCAAYyF,UAAU,CAACC,QAAUzF,cAAcyF,MAAME,MAAM,CAACJ,KAAK;;kDACzG,KAACnJ;wCAASmJ,OAAM;kDAAI;;oCACnBxG,UAAU6C,GAAG,CAAC,CAACC,yBACd,KAACzF;4CAA4BmJ,OAAO1D,SAASC,GAAG;sDAC7CD,SAASzC,IAAI;2CADDyC,SAASC,GAAG;;;4BAK9B1D,UAAU,CAACA,OAAO4E,aAAa,iBAC9B,MAACnH;gCAAI+I,IAAI;oCAAE2B,SAAS;oCAAQe,KAAK;oCAAKM,qBAAqB;wCAAEC,IAAI;wCAAOC,IAAI;oCAAU;gCAAE;;kDACtF,KAACvL;wCAAWyE,SAAQ;wCAAQyD,OAAM;wCAAiBG,IAAI;4CAAEmD,YAAY;wCAAS;kDAC3E;;kDAEH,KAACzL;wCAAUuD,OAAM;wCAAS0F,OAAOtF,QAAQvC,KAAK;wCAAE8H,UAAU,CAACC,QAAUvF,WAAW,aAAKD;gDAASvC,OAAO+H,MAAME,MAAM,CAACJ,KAAK;;wCAAKX,IAAI;4CAAEmD,YAAY;wCAAS;;kDACvJ,KAACzL;wCAAUuD,OAAM;wCAAO0F,OAAOtF,QAAQrC,IAAI;wCAAE4H,UAAU,CAACC,QAAUvF,WAAW,aAAKD;gDAASrC,MAAM6H,MAAME,MAAM,CAACJ,KAAK;;;kDACnH,KAACjJ;wCAAUuD,OAAM;wCAAQ0F,OAAOtF,QAAQpC,KAAK;wCAAE2H,UAAU,CAACC,QAAUvF,WAAW,aAAKD;gDAASpC,OAAO4H,MAAME,MAAM,CAACJ,KAAK;;;kDACtH,KAACjJ;wCAAUuD,OAAM;wCAAc0F,OAAOtF,QAAQnC,UAAU;wCAAE0H,UAAU,CAACC,QAAUvF,WAAW,aAAKD;gDAASnC,YAAY2H,MAAME,MAAM,CAACJ,KAAK;;;kDACtI,KAACjJ;wCACCuD,OAAM;wCACN0F,OAAOtF,QAAQlC,OAAO;wCACtByH,UAAU,CAACC,QAAUvF,WAAW,aAAKD;gDAASlC,SAAS0H,MAAME,MAAM,CAACJ,KAAK,CAACyC,WAAW,GAAGC,KAAK,CAAC,GAAG;;;;iCAGnG;;;kCAEN,MAAChM;;0CACC,KAACH;gCAAOwI,SAAS,IAAM5E,UAAU;0CAAS;;0CAC1C,KAAC5D;gCAAOkF,SAAQ;gCAAYsE,UAAUnF,QAAQ,CAACR,KAAKoD,IAAI;gCAAIuB,SAAS,IAAM,KAAKzB;0CAC7E;;;;;;YAIN1B,YAAY+G,MAAM;;;AAGzB;AACAlK,eAAemK,WAAW,GAAG;AAE7B,eAAenK,eAAc"}
|
|
@@ -62,6 +62,12 @@ export interface PosDisplayResult<T> {
|
|
|
62
62
|
error?: string;
|
|
63
63
|
}
|
|
64
64
|
export declare function readStoredToken(): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Keeps the display's token, or forgets it. Core keeps a copy too (AGL-4042):
|
|
67
|
+
* the display's credential, which another plugin's screen on this display
|
|
68
|
+
* sends its own server so core's verifier can say which store's display it
|
|
69
|
+
* is. Forgotten with it when the display is unpaired.
|
|
70
|
+
*/
|
|
65
71
|
export declare function storeToken(token: string | null): void;
|
|
66
72
|
/**
|
|
67
73
|
* Exchanges a register's code for this device's token. `mode` is the kind of
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
import { rememberCustomerDisplayCredential } from "@aglyn/aglyn/plugin-manager/plugin-customer-display";
|
|
17
18
|
/**
|
|
18
19
|
* The customer display's half of `/api/commerce/pos-display` (AGL-3608).
|
|
19
20
|
*
|
|
@@ -31,7 +32,13 @@ export function readStoredToken() {
|
|
|
31
32
|
return null;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Keeps the display's token, or forgets it. Core keeps a copy too (AGL-4042):
|
|
37
|
+
* the display's credential, which another plugin's screen on this display
|
|
38
|
+
* sends its own server so core's verifier can say which store's display it
|
|
39
|
+
* is. Forgotten with it when the display is unpaired.
|
|
40
|
+
*/ export function storeToken(token) {
|
|
41
|
+
rememberCustomerDisplayCredential(token);
|
|
35
42
|
try {
|
|
36
43
|
if (token) window.localStorage.setItem(POS_DISPLAY_TOKEN_KEY, token);
|
|
37
44
|
else window.localStorage.removeItem(POS_DISPLAY_TOKEN_KEY);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-display/pos-display-api.ts"],"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 type * as CommerceModel from '../../../model'\n\n/**\n * The customer display's half of `/api/commerce/pos-display` (AGL-3608).\n *\n * Every call carries the DISPLAY token, never a staff session: the screen\n * faces the public, and the token opens one register's display state and\n * nothing else. The route answers 401 when the token is unknown or revoked,\n * which the page reads as \"pair again\".\n */\nexport const POS_DISPLAY_ENDPOINT = '/api/commerce/pos-display'\n\n/** Where the paired token lives on the device. */\nexport const POS_DISPLAY_TOKEN_KEY = 'aglyn.posDisplayToken'\n\nexport const POS_DISPLAY_TOKEN_HEADER = 'X-Pos-Display-Token'\n\n/** The store's look for the idle and thank-you screens. */\nexport interface PosDisplayBranding {\n name: string\n logoUrl: string | null\n logoDarkUrl: string | null\n message: string\n}\n\n/** The state as the route hands it to the display. */\nexport type PosDisplayPublicState = Omit<CommerceModel.PosDisplayState, 'response'> & {\n answered: boolean\n}\n\n/** What the customer sends back for the current prompt. */\nexport interface PosDisplayAnswer {\n promptId: string\n tipChoice?: 'percent' | 'custom' | 'none'\n tipPercent?: number\n tipCents?: number\n receiptChannel?: CommerceModel.PosReceiptChannel\n email?: string\n phone?: string\n marketingOptIn?: boolean\n}\n\n/**\n * A call's outcome, with the status the page branches on: `value` when `ok`,\n * `error` when not. One flat shape rather than a union, because the\n * workspace compiles without `strict` and an `ok` check would not narrow one.\n */\nexport interface PosDisplayResult<T> {\n ok: boolean\n /** The HTTP status, or 0 when the request never landed. */\n status: number\n value?: T\n error?: string\n}\n\nexport function readStoredToken(): string | null {\n try {\n return window.localStorage.getItem(POS_DISPLAY_TOKEN_KEY) || null\n } catch {\n return null\n }\n}\n\nexport function storeToken(token: string | null): void {\n try {\n if (token) window.localStorage.setItem(POS_DISPLAY_TOKEN_KEY, token)\n else window.localStorage.removeItem(POS_DISPLAY_TOKEN_KEY)\n } catch {\n // Storage blocked (a private window, a locked-down kiosk browser): the\n // display still works until it reloads, then asks for a code again.\n }\n}\n\nasync function call<T>(\n init: { method: 'GET'; query: string } | { method: 'POST'; body: Record<string, unknown> },\n token: string | null,\n): Promise<PosDisplayResult<T>> {\n const headers: Record<string, string> = {}\n if (token) headers[POS_DISPLAY_TOKEN_HEADER] = token\n if (init.method === 'POST') headers['Content-Type'] = 'application/json'\n try {\n const response = await fetch(\n init.method === 'GET' ? `${POS_DISPLAY_ENDPOINT}?${init.query}` : POS_DISPLAY_ENDPOINT,\n {\n method: init.method,\n headers,\n cache: 'no-store',\n ...(init.method === 'POST' ? { body: JSON.stringify(init.body) } : {}),\n },\n )\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (!response.ok) {\n return {\n ok: false,\n status: response.status,\n error: String(payload?.['error'] ?? 'Something went wrong. Try again.'),\n }\n }\n return { ok: true, status: response.status, value: (payload ?? {}) as T }\n } catch {\n // Offline or the request never landed: status 0, which the poll treats\n // as \"try again next tick\" rather than as a reason to unpair.\n return { ok: false, status: 0, error: 'No connection. Trying again…' }\n }\n}\n\n/**\n * Exchanges a register's code for this device's token. `mode` is the kind of\n * screen this page is — a customer display, or a self-service kiosk\n * (AGL-3623) — and a code made for the other kind is refused.\n */\nexport function pairDisplay(code: string, mode: CommerceModel.PosDeviceMode = 'display') {\n return call<{ token: string; mode?: CommerceModel.PosDeviceMode; branding: PosDisplayBranding }>(\n {\n method: 'POST',\n body: {\n action: 'pair',\n code,\n mode,\n label: mode === 'kiosk' ? 'Self-service kiosk' : 'Customer display',\n },\n },\n null,\n )\n}\n\nexport function pollDisplay(token: string, withBranding: boolean) {\n return call<{ state: PosDisplayPublicState; branding?: PosDisplayBranding }>(\n { method: 'GET', query: `action=poll${withBranding ? '&branding=true' : ''}` },\n token,\n )\n}\n\nexport function respondToDisplay(token: string, response: PosDisplayAnswer) {\n return call<{ ok: true }>({ method: 'POST', body: { action: 'respond', response } }, token)\n}\n\nexport function forgetDisplay(token: string) {\n return call<{ ok: true }>({ method: 'POST', body: { action: 'forget' } }, token)\n}\n\n/**\n * Minor units as the register shows them, in the store's currency (the\n * display state's `currency`; US dollars when a state predates it). A\n * zero-decimal currency (JPY) has no minor unit to divide out.\n */\nexport function displayMoney(cents: number, currency?: string | null): string {\n const code = String(currency || 'usd').toUpperCase()\n const amount = Number(cents) || 0\n try {\n const format = new Intl.NumberFormat('en-US', { style: 'currency', currency: code })\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2\n return format.format(amount / 10 ** digits)\n } catch {\n return `${(amount / 100).toFixed(2)} ${code}`\n }\n}\n\n/**\n * Dollars typed on the display as whole cents, or null when the entry is not\n * an amount (`12`, `12.5` and `$12.50` are; `12.505` and `abc` are not).\n */\nexport function dollarsToCents(input: string): number | null {\n const cleaned = String(input ?? '').trim().replace(/^\\$/, '')\n if (!/^\\d+(\\.\\d{0,2})?$/.test(cleaned)) return null\n return Math.round(Number(cleaned) * 100)\n}\n"],"names":["POS_DISPLAY_ENDPOINT","POS_DISPLAY_TOKEN_KEY","POS_DISPLAY_TOKEN_HEADER","readStoredToken","window","localStorage","getItem","storeToken","token","setItem","removeItem","call","init","headers","method","response","fetch","query","cache","body","JSON","stringify","payload","json","catch","ok","status","error","String","value","pairDisplay","code","mode","action","label","pollDisplay","withBranding","respondToDisplay","forgetDisplay","displayMoney","cents","currency","toUpperCase","amount","Number","format","Intl","NumberFormat","style","digits","resolvedOptions","maximumFractionDigits","toFixed","dollarsToCents","input","cleaned","trim","replace","test","Math","round"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-display/pos-display-api.ts"],"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 type * as CommerceModel from '../../../model'\nimport { rememberCustomerDisplayCredential } from '@aglyn/aglyn/plugin-manager/plugin-customer-display'\n\n/**\n * The customer display's half of `/api/commerce/pos-display` (AGL-3608).\n *\n * Every call carries the DISPLAY token, never a staff session: the screen\n * faces the public, and the token opens one register's display state and\n * nothing else. The route answers 401 when the token is unknown or revoked,\n * which the page reads as \"pair again\".\n */\nexport const POS_DISPLAY_ENDPOINT = '/api/commerce/pos-display'\n\n/** Where the paired token lives on the device. */\nexport const POS_DISPLAY_TOKEN_KEY = 'aglyn.posDisplayToken'\n\nexport const POS_DISPLAY_TOKEN_HEADER = 'X-Pos-Display-Token'\n\n/** The store's look for the idle and thank-you screens. */\nexport interface PosDisplayBranding {\n name: string\n logoUrl: string | null\n logoDarkUrl: string | null\n message: string\n}\n\n/** The state as the route hands it to the display. */\nexport type PosDisplayPublicState = Omit<CommerceModel.PosDisplayState, 'response'> & {\n answered: boolean\n}\n\n/** What the customer sends back for the current prompt. */\nexport interface PosDisplayAnswer {\n promptId: string\n tipChoice?: 'percent' | 'custom' | 'none'\n tipPercent?: number\n tipCents?: number\n receiptChannel?: CommerceModel.PosReceiptChannel\n email?: string\n phone?: string\n marketingOptIn?: boolean\n}\n\n/**\n * A call's outcome, with the status the page branches on: `value` when `ok`,\n * `error` when not. One flat shape rather than a union, because the\n * workspace compiles without `strict` and an `ok` check would not narrow one.\n */\nexport interface PosDisplayResult<T> {\n ok: boolean\n /** The HTTP status, or 0 when the request never landed. */\n status: number\n value?: T\n error?: string\n}\n\nexport function readStoredToken(): string | null {\n try {\n return window.localStorage.getItem(POS_DISPLAY_TOKEN_KEY) || null\n } catch {\n return null\n }\n}\n\n/**\n * Keeps the display's token, or forgets it. Core keeps a copy too (AGL-4042):\n * the display's credential, which another plugin's screen on this display\n * sends its own server so core's verifier can say which store's display it\n * is. Forgotten with it when the display is unpaired.\n */\nexport function storeToken(token: string | null): void {\n rememberCustomerDisplayCredential(token)\n try {\n if (token) window.localStorage.setItem(POS_DISPLAY_TOKEN_KEY, token)\n else window.localStorage.removeItem(POS_DISPLAY_TOKEN_KEY)\n } catch {\n // Storage blocked (a private window, a locked-down kiosk browser): the\n // display still works until it reloads, then asks for a code again.\n }\n}\n\nasync function call<T>(\n init: { method: 'GET'; query: string } | { method: 'POST'; body: Record<string, unknown> },\n token: string | null,\n): Promise<PosDisplayResult<T>> {\n const headers: Record<string, string> = {}\n if (token) headers[POS_DISPLAY_TOKEN_HEADER] = token\n if (init.method === 'POST') headers['Content-Type'] = 'application/json'\n try {\n const response = await fetch(\n init.method === 'GET' ? `${POS_DISPLAY_ENDPOINT}?${init.query}` : POS_DISPLAY_ENDPOINT,\n {\n method: init.method,\n headers,\n cache: 'no-store',\n ...(init.method === 'POST' ? { body: JSON.stringify(init.body) } : {}),\n },\n )\n const payload = (await response.json().catch(() => null)) as Record<string, unknown> | null\n if (!response.ok) {\n return {\n ok: false,\n status: response.status,\n error: String(payload?.['error'] ?? 'Something went wrong. Try again.'),\n }\n }\n return { ok: true, status: response.status, value: (payload ?? {}) as T }\n } catch {\n // Offline or the request never landed: status 0, which the poll treats\n // as \"try again next tick\" rather than as a reason to unpair.\n return { ok: false, status: 0, error: 'No connection. Trying again…' }\n }\n}\n\n/**\n * Exchanges a register's code for this device's token. `mode` is the kind of\n * screen this page is — a customer display, or a self-service kiosk\n * (AGL-3623) — and a code made for the other kind is refused.\n */\nexport function pairDisplay(code: string, mode: CommerceModel.PosDeviceMode = 'display') {\n return call<{ token: string; mode?: CommerceModel.PosDeviceMode; branding: PosDisplayBranding }>(\n {\n method: 'POST',\n body: {\n action: 'pair',\n code,\n mode,\n label: mode === 'kiosk' ? 'Self-service kiosk' : 'Customer display',\n },\n },\n null,\n )\n}\n\nexport function pollDisplay(token: string, withBranding: boolean) {\n return call<{ state: PosDisplayPublicState; branding?: PosDisplayBranding }>(\n { method: 'GET', query: `action=poll${withBranding ? '&branding=true' : ''}` },\n token,\n )\n}\n\nexport function respondToDisplay(token: string, response: PosDisplayAnswer) {\n return call<{ ok: true }>({ method: 'POST', body: { action: 'respond', response } }, token)\n}\n\nexport function forgetDisplay(token: string) {\n return call<{ ok: true }>({ method: 'POST', body: { action: 'forget' } }, token)\n}\n\n/**\n * Minor units as the register shows them, in the store's currency (the\n * display state's `currency`; US dollars when a state predates it). A\n * zero-decimal currency (JPY) has no minor unit to divide out.\n */\nexport function displayMoney(cents: number, currency?: string | null): string {\n const code = String(currency || 'usd').toUpperCase()\n const amount = Number(cents) || 0\n try {\n const format = new Intl.NumberFormat('en-US', { style: 'currency', currency: code })\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2\n return format.format(amount / 10 ** digits)\n } catch {\n return `${(amount / 100).toFixed(2)} ${code}`\n }\n}\n\n/**\n * Dollars typed on the display as whole cents, or null when the entry is not\n * an amount (`12`, `12.5` and `$12.50` are; `12.505` and `abc` are not).\n */\nexport function dollarsToCents(input: string): number | null {\n const cleaned = String(input ?? '').trim().replace(/^\\$/, '')\n if (!/^\\d+(\\.\\d{0,2})?$/.test(cleaned)) return null\n return Math.round(Number(cleaned) * 100)\n}\n"],"names":["rememberCustomerDisplayCredential","POS_DISPLAY_ENDPOINT","POS_DISPLAY_TOKEN_KEY","POS_DISPLAY_TOKEN_HEADER","readStoredToken","window","localStorage","getItem","storeToken","token","setItem","removeItem","call","init","headers","method","response","fetch","query","cache","body","JSON","stringify","payload","json","catch","ok","status","error","String","value","pairDisplay","code","mode","action","label","pollDisplay","withBranding","respondToDisplay","forgetDisplay","displayMoney","cents","currency","toUpperCase","amount","Number","format","Intl","NumberFormat","style","digits","resolvedOptions","maximumFractionDigits","toFixed","dollarsToCents","input","cleaned","trim","replace","test","Math","round"],"mappings":"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"}
|
|
@@ -3,6 +3,19 @@ import type { ConsolePublicPageProps } from '@aglyn/aglyn';
|
|
|
3
3
|
export declare const POS_DISPLAY_ACTIVE_POLL_MS = 1000;
|
|
4
4
|
/** And between sales, when nothing on it is changing. */
|
|
5
5
|
export declare const POS_DISPLAY_IDLE_POLL_MS = 3000;
|
|
6
|
+
/** This page's own address, where another plugin's screen sends the display back. */
|
|
7
|
+
export declare const POS_DISPLAY_PAGE_PATH = "/kiosk/commerce/pos-display";
|
|
8
|
+
/**
|
|
9
|
+
* Whether this tab may open the screen of a prompt, marking it opened. Session
|
|
10
|
+
* storage, so it survives the trip to the plugin's page and back and is gone
|
|
11
|
+
* with the tab. A browser that refuses storage opens no screen at all: it
|
|
12
|
+
* could not remember coming back, and would open the same one again.
|
|
13
|
+
*/
|
|
14
|
+
export declare function claimDisplayScreen(promptId: string): boolean;
|
|
15
|
+
/** Leaves for another plugin's screen; an object so a spec can watch it. */
|
|
16
|
+
export declare const posDisplayNavigation: {
|
|
17
|
+
open(href: string): void;
|
|
18
|
+
};
|
|
6
19
|
/**
|
|
7
20
|
* The screen a register turns toward its customer (AGL-3608), served at
|
|
8
21
|
* `/kiosk/commerce/pos-display` with no staff session.
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/ 'use client';
|
|
17
17
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { customerDisplayScreenHref, rememberCustomerDisplayCredential } from "@aglyn/aglyn/plugin-manager/plugin-customer-display";
|
|
18
19
|
import Alert from "@mui/material/Alert";
|
|
19
20
|
import Box from "@mui/material/Box";
|
|
20
21
|
import Button from "@mui/material/Button";
|
|
@@ -37,6 +38,32 @@ import { PosDisplayTipScreen } from "./pos-display/tip-screen.js";
|
|
|
37
38
|
/** How often the display asks for news while a sale is on screen. */ export const POS_DISPLAY_ACTIVE_POLL_MS = 1000;
|
|
38
39
|
/** And between sales, when nothing on it is changing. */ export const POS_DISPLAY_IDLE_POLL_MS = 3000;
|
|
39
40
|
/** The store's name and logo are re-read this often, so an edit reaches the screen. */ const BRANDING_REFRESH_MS = 10 * 60 * 1000;
|
|
41
|
+
/** This page's own address, where another plugin's screen sends the display back. */ export const POS_DISPLAY_PAGE_PATH = '/kiosk/commerce/pos-display';
|
|
42
|
+
/** The prompts of the plugin screens this tab already opened, so coming back opens none again. */ const OPENED_SCREENS_KEY = 'aglyn.posDisplayOpenedScreens';
|
|
43
|
+
/**
|
|
44
|
+
* Whether this tab may open the screen of a prompt, marking it opened. Session
|
|
45
|
+
* storage, so it survives the trip to the plugin's page and back and is gone
|
|
46
|
+
* with the tab. A browser that refuses storage opens no screen at all: it
|
|
47
|
+
* could not remember coming back, and would open the same one again.
|
|
48
|
+
*/ export function claimDisplayScreen(promptId) {
|
|
49
|
+
try {
|
|
50
|
+
var _window_sessionStorage_getItem;
|
|
51
|
+
const opened = JSON.parse((_window_sessionStorage_getItem = window.sessionStorage.getItem(OPENED_SCREENS_KEY)) != null ? _window_sessionStorage_getItem : '[]');
|
|
52
|
+
if (opened.includes(promptId)) return false;
|
|
53
|
+
window.sessionStorage.setItem(OPENED_SCREENS_KEY, JSON.stringify([
|
|
54
|
+
...opened,
|
|
55
|
+
promptId
|
|
56
|
+
].slice(-20)));
|
|
57
|
+
return true;
|
|
58
|
+
} catch (unused) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Leaves for another plugin's screen; an object so a spec can watch it. */ export const posDisplayNavigation = {
|
|
63
|
+
open (href) {
|
|
64
|
+
window.location.assign(href);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
40
67
|
/**
|
|
41
68
|
* The screen a register turns toward its customer (AGL-3608), served at
|
|
42
69
|
* `/kiosk/commerce/pos-display` with no staff session.
|
|
@@ -64,7 +91,11 @@ import { PosDisplayTipScreen } from "./pos-display/tip-screen.js";
|
|
|
64
91
|
stateRef.current = state;
|
|
65
92
|
const brandingAtRef = useRef(0);
|
|
66
93
|
useEffect(()=>{
|
|
67
|
-
|
|
94
|
+
const stored = readStoredToken();
|
|
95
|
+
// A display paired before core kept the credential (AGL-4042) hands it
|
|
96
|
+
// over here, so another plugin's screen on it works without pairing again.
|
|
97
|
+
rememberCustomerDisplayCredential(stored);
|
|
98
|
+
setToken(stored);
|
|
68
99
|
}, []);
|
|
69
100
|
const unpaired = useCallback(()=>{
|
|
70
101
|
storeToken(null);
|
|
@@ -141,6 +172,16 @@ import { PosDisplayTipScreen } from "./pos-display/tip-screen.js";
|
|
|
141
172
|
token,
|
|
142
173
|
unpaired
|
|
143
174
|
]);
|
|
175
|
+
// Another plugin's screen (AGL-4042): opened once per prompt, at the
|
|
176
|
+
// plugin's own public page, which sends the display back here when the
|
|
177
|
+
// customer is done. Back here, the same prompt shows the store's screen.
|
|
178
|
+
useEffect(()=>{
|
|
179
|
+
if ((state == null ? void 0 : state.mode) !== 'screen' || !state.screen || !state.promptId) return;
|
|
180
|
+
const href = customerDisplayScreenHref(state.screen, POS_DISPLAY_PAGE_PATH);
|
|
181
|
+
if (href && claimDisplayScreen(state.promptId)) posDisplayNavigation.open(href);
|
|
182
|
+
}, [
|
|
183
|
+
state
|
|
184
|
+
]);
|
|
144
185
|
// Keep the screen on while paired. Best effort: a browser without the
|
|
145
186
|
// Wake Lock API, or one that refuses it, just follows its own sleep.
|
|
146
187
|
useEffect(()=>{
|
|
@@ -269,7 +310,8 @@ import { PosDisplayTipScreen } from "./pos-display/tip-screen.js";
|
|
|
269
310
|
branding: branding,
|
|
270
311
|
message: (branding == null ? void 0 : branding.message) || 'Welcome'
|
|
271
312
|
});
|
|
272
|
-
|
|
313
|
+
// A plugin's screen opens its own page; back here, the store's screen shows.
|
|
314
|
+
if (!state || state.mode === 'idle' || state.mode === 'screen') return idle;
|
|
273
315
|
if (state.mode === 'thanks') {
|
|
274
316
|
if (thanksOver) return idle;
|
|
275
317
|
return /*#__PURE__*/ _jsx(PosDisplayBrandScreen, {
|