@aglyn/plugins-commerce 1.0.0-beta.277 → 1.0.0-beta.282
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -14
- package/src/lib/components/commerce-console-page.js +33 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/payments-settings-card.component.js +1 -1
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-api.d.ts +122 -0
- package/src/lib/components/console/pos/pos-hardware-api.js +90 -0
- package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.d.ts +58 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.js +101 -0
- package/src/lib/components/console/pos/pos-reader-splash-api.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.js +5 -0
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-card.component.d.ts +26 -0
- package/src/lib/components/console/pos-hardware-card.component.js +456 -0
- package/src/lib/components/console/pos-hardware-card.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.d.ts +14 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +519 -0
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.d.ts +27 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +444 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.d.ts +9 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js +37 -0
- package/src/lib/components/console/pos-ops/pos-check-in-zone.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +24 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +346 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.d.ts +5 -1
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js +83 -4
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.d.ts +35 -0
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js +546 -0
- package/src/lib/components/console/pos-ops/pos-day-totals-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +2 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +20 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-ops-api.d.ts +1 -1
- package/src/lib/components/console/pos-ops/pos-ops-api.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +6 -3
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.d.ts +22 -0
- package/src/lib/components/console/pos-reader-splash-setting.component.js +275 -0
- package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.d.ts +14 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.js +301 -0
- package/src/lib/components/console/pos-reader-splash-staff-page.component.js.map +1 -0
- package/src/lib/components/console/pos-zones.d.ts +37 -3
- package/src/lib/components/console/pos-zones.js +11 -1
- package/src/lib/components/console/pos-zones.js.map +1 -1
- package/src/lib/components/console/product-check-in-fields.component.d.ts +20 -0
- package/src/lib/components/console/product-check-in-fields.component.js +172 -0
- package/src/lib/components/console/product-check-in-fields.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +48 -9
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-register-fields.component.d.ts +12 -0
- package/src/lib/components/console/product-register-fields.component.js +39 -1
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +21 -6
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/reservations-card.component.js +239 -70
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
- package/src/lib/components/reservation-widget.js +16 -0
- package/src/lib/components/reservation-widget.js.map +1 -1
- package/src/lib/constants/operator-alerts.d.ts +6 -0
- package/src/lib/constants/operator-alerts.js +20 -1
- package/src/lib/constants/operator-alerts.js.map +1 -1
- package/src/lib/declarations.console-server.js +7 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +26 -0
- package/src/lib/declarations.js +34 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/model/commerce-check-in-product.d.ts +37 -0
- package/src/lib/model/commerce-check-in-product.js +49 -0
- package/src/lib/model/commerce-check-in-product.js.map +1 -0
- package/src/lib/model/commerce-check-in.d.ts +187 -0
- package/src/lib/model/commerce-check-in.js +468 -0
- package/src/lib/model/commerce-check-in.js.map +1 -0
- package/src/lib/model/commerce-pos-day-report.d.ts +209 -0
- package/src/lib/model/commerce-pos-day-report.js +572 -0
- package/src/lib/model/commerce-pos-day-report.js.map +1 -0
- package/src/lib/model/commerce-pos-offline.d.ts +65 -3
- package/src/lib/model/commerce-pos-offline.js +104 -7
- package/src/lib/model/commerce-pos-offline.js.map +1 -1
- package/src/lib/model/commerce-pos-ops.d.ts +3 -0
- package/src/lib/model/commerce-pos-ops.js +1 -0
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +43 -3
- package/src/lib/model/commerce-pos.js +73 -5
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-reservations.d.ts +73 -7
- package/src/lib/model/commerce-reservations.js +90 -10
- package/src/lib/model/commerce-reservations.js.map +1 -1
- package/src/lib/model/commerce.d.ts +40 -0
- package/src/lib/model/commerce.js +22 -4
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +1 -0
- package/src/lib/model/index.js +1 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/plugin-permissions.d.ts +1 -1
- package/src/lib/model/plugin-permissions.js +2 -1
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/model/pos-hardware.d.ts +288 -0
- package/src/lib/model/pos-hardware.js +499 -0
- package/src/lib/model/pos-hardware.js.map +1 -0
- package/src/lib/model/pos-offline-card-limits.d.ts +20 -0
- package/src/lib/model/pos-offline-card-limits.js +28 -0
- package/src/lib/model/pos-offline-card-limits.js.map +1 -0
- package/src/lib/model/pos-reader-splash.d.ts +114 -0
- package/src/lib/model/pos-reader-splash.js +141 -0
- package/src/lib/model/pos-reader-splash.js.map +1 -0
- package/src/lib/model/product-write.d.ts +6 -0
- package/src/lib/plugin-config.d.ts +10 -0
- package/src/lib/plugin-config.js +40 -0
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +28 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/cart-checkout.js +3 -1
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.js +12 -1
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/catalog.js +49 -12
- package/src/lib/server/catalog.js.map +1 -1
- package/src/lib/server/checkout-extras.js +1 -1
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +7 -0
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +8 -1
- package/src/lib/server/person-eraser.js +23 -1
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-check-in.d.ts +49 -0
- package/src/lib/server/pos-check-in.js +652 -0
- package/src/lib/server/pos-check-in.js.map +1 -0
- package/src/lib/server/pos-day-report.d.ts +46 -0
- package/src/lib/server/pos-day-report.js +299 -0
- package/src/lib/server/pos-day-report.js.map +1 -0
- package/src/lib/server/pos-hardware-admin.d.ts +50 -0
- package/src/lib/server/pos-hardware-admin.js +366 -0
- package/src/lib/server/pos-hardware-admin.js.map +1 -0
- package/src/lib/server/pos-hardware-notify.d.ts +27 -0
- package/src/lib/server/pos-hardware-notify.js +142 -0
- package/src/lib/server/pos-hardware-notify.js.map +1 -0
- package/src/lib/server/pos-hardware-user-eraser.d.ts +26 -0
- package/src/lib/server/pos-hardware-user-eraser.js +67 -0
- package/src/lib/server/pos-hardware-user-eraser.js.map +1 -0
- package/src/lib/server/pos-hardware-webhook.d.ts +31 -0
- package/src/lib/server/pos-hardware-webhook.js +176 -0
- package/src/lib/server/pos-hardware-webhook.js.map +1 -0
- package/src/lib/server/pos-hardware.d.ts +58 -0
- package/src/lib/server/pos-hardware.js +234 -0
- package/src/lib/server/pos-hardware.js.map +1 -0
- package/src/lib/server/pos-offline-card-reconcile.d.ts +38 -0
- package/src/lib/server/pos-offline-card-reconcile.js +58 -0
- package/src/lib/server/pos-offline-card-reconcile.js.map +1 -0
- package/src/lib/server/pos-offline-sync.d.ts +32 -0
- package/src/lib/server/pos-offline-sync.js +191 -15
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-ops-routes.d.ts +4 -2
- package/src/lib/server/pos-ops-routes.js +14 -2
- package/src/lib/server/pos-ops-routes.js.map +1 -1
- package/src/lib/server/pos-order.js +39 -51
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.js +8 -4
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-reader-splash-admin.d.ts +36 -0
- package/src/lib/server/pos-reader-splash-admin.js +295 -0
- package/src/lib/server/pos-reader-splash-admin.js.map +1 -0
- package/src/lib/server/pos-reader-splash-render.d.ts +40 -0
- package/src/lib/server/pos-reader-splash-render.js +138 -0
- package/src/lib/server/pos-reader-splash-render.js.map +1 -0
- package/src/lib/server/pos-reader-splash-server.d.ts +32 -0
- package/src/lib/server/pos-reader-splash-server.js +32 -0
- package/src/lib/server/pos-reader-splash-server.js.map +1 -0
- package/src/lib/server/pos-reader-splash.d.ts +105 -0
- package/src/lib/server/pos-reader-splash.js +548 -0
- package/src/lib/server/pos-reader-splash.js.map +1 -0
- package/src/lib/server/pos-sale.d.ts +2 -1
- package/src/lib/server/pos-sale.js +3 -1
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-terminal.d.ts +67 -4
- package/src/lib/server/pos-terminal.js +239 -32
- package/src/lib/server/pos-terminal.js.map +1 -1
- package/src/lib/server/process-restock.js +4 -0
- package/src/lib/server/process-restock.js.map +1 -1
- package/src/lib/server/product-card.js +2 -2
- package/src/lib/server/product-card.js.map +1 -1
- package/src/lib/server/product-catalog.d.ts +2 -0
- package/src/lib/server/product-catalog.js +11 -4
- package/src/lib/server/product-catalog.js.map +1 -1
- package/src/lib/server/product.js +3 -1
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/related.js +8 -1
- package/src/lib/server/related.js.map +1 -1
- package/src/lib/server/reservation-availability-query.d.ts +35 -0
- package/src/lib/server/reservation-availability-query.js +34 -0
- package/src/lib/server/reservation-availability-query.js.map +1 -0
- package/src/lib/server/reservation-availability.d.ts +21 -0
- package/src/lib/server/reservation-availability.js +64 -10
- package/src/lib/server/reservation-availability.js.map +1 -1
- package/src/lib/server/reservation-walk-in.d.ts +28 -0
- package/src/lib/server/reservation-walk-in.js +166 -0
- package/src/lib/server/reservation-walk-in.js.map +1 -0
- package/src/lib/server/reserve.js +13 -10
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/reviews.js +3 -1
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +5 -2
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +26 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/fake-firestore.js +72 -0
- package/src/lib/testing/fake-firestore.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-commerce",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.282",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,26 +25,29 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-next": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
36
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
37
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
38
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
39
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.282",
|
|
29
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.282",
|
|
30
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.282",
|
|
31
|
+
"@aglyn/shared-ui-next": "1.0.0-beta.282",
|
|
32
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.282",
|
|
33
|
+
"@aglyn/shared-util-email": "1.0.0-beta.282",
|
|
34
|
+
"@aglyn/shared-util-http": "1.0.0-beta.282",
|
|
35
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.282",
|
|
36
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.282",
|
|
37
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.282",
|
|
38
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.282",
|
|
39
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.282",
|
|
40
40
|
"@stripe/react-stripe-js": "^6.12.0",
|
|
41
41
|
"@stripe/stripe-js": "^9.17.0",
|
|
42
42
|
"@swc/helpers": "0.5.23",
|
|
43
|
-
"
|
|
43
|
+
"dayjs": "^1.11.23",
|
|
44
|
+
"qrcode.react": "^4.2.0",
|
|
45
|
+
"sharp": "^0.35.5"
|
|
44
46
|
},
|
|
45
47
|
"peerDependencies": {
|
|
46
48
|
"@mui/material": "^9.3.1",
|
|
47
49
|
"@mui/x-data-grid": "^9.12.0",
|
|
50
|
+
"@mui/x-date-pickers": "^9.15.0",
|
|
48
51
|
"firebase": "^13.0.0",
|
|
49
52
|
"firebase-admin": "^14.3.0",
|
|
50
53
|
"next": "^16.3.3",
|
|
@@ -31,6 +31,8 @@ import PickupDeliveryQueueCard from "./console/pickup-delivery-queue-card.compon
|
|
|
31
31
|
import MemberPostsCard from "./console/member-posts-card.component.js";
|
|
32
32
|
import OrderWebhooksCard from "./console/order-webhooks-card.component.js";
|
|
33
33
|
import PaymentsSettingsCard from "./console/payments-settings-card.component.js";
|
|
34
|
+
import PosCheckInsCard from "./console/pos-ops/pos-check-ins-card.component.js";
|
|
35
|
+
import PosDayTotalsCard from "./console/pos-ops/pos-day-totals-card.component.js";
|
|
34
36
|
import PosShiftHistoryCard from "./console/pos-ops/pos-shift-history-card.component.js";
|
|
35
37
|
import PosStaffPinsCard from "./console/pos-ops/pos-staff-pins-card.component.js";
|
|
36
38
|
import PaymentMethodsCard from "./console/payment-methods-card.component.js";
|
|
@@ -39,6 +41,7 @@ import RecoveryQueueCard from "./console/recovery-queue-card.component.js";
|
|
|
39
41
|
import RegistersCard from "./console/registers-card.component.js";
|
|
40
42
|
import RegisterHardwareCards from "./console/register-hardware-card.component.js";
|
|
41
43
|
import PosDevicesCard from "./console/pos-devices-card.component.js";
|
|
44
|
+
import PosHardwareCard from "./console/pos-hardware-card.component.js";
|
|
42
45
|
import ReservationsCard from "./console/reservations-card.component.js";
|
|
43
46
|
import ReturnSettingsCard from "./console/return-settings-card.component.js";
|
|
44
47
|
import ReturnsCard from "./console/returns-card.component.js";
|
|
@@ -185,6 +188,28 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
185
188
|
hostId: hostId
|
|
186
189
|
})
|
|
187
190
|
},
|
|
191
|
+
// One day's or one event's totals across every register, shift
|
|
192
|
+
// and cashier (AGL-4037), above the shifts it adds up.
|
|
193
|
+
{
|
|
194
|
+
size: {
|
|
195
|
+
xs: 12
|
|
196
|
+
},
|
|
197
|
+
children: /*#__PURE__*/ _jsx(PosDayTotalsCard, {
|
|
198
|
+
hostId: hostId,
|
|
199
|
+
canManagePos: canManagePos
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
// Who is due at the window and who checked in (AGL-4043), beside
|
|
203
|
+
// the day's totals.
|
|
204
|
+
{
|
|
205
|
+
size: {
|
|
206
|
+
xs: 12
|
|
207
|
+
},
|
|
208
|
+
children: /*#__PURE__*/ _jsx(PosCheckInsCard, {
|
|
209
|
+
hostId: hostId,
|
|
210
|
+
canManagePos: canManagePos
|
|
211
|
+
})
|
|
212
|
+
},
|
|
188
213
|
{
|
|
189
214
|
size: {
|
|
190
215
|
xs: 12
|
|
@@ -347,7 +372,14 @@ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot
|
|
|
347
372
|
/*#__PURE__*/ _jsx(PosDevicesCard, {
|
|
348
373
|
hostId: hostId,
|
|
349
374
|
canManagePos: canManagePos
|
|
350
|
-
}, "devices")
|
|
375
|
+
}, "devices"),
|
|
376
|
+
// Card readers bought from the platform (AGL-4038), after the card
|
|
377
|
+
// that registers them. Draws nothing until the deployment opens the
|
|
378
|
+
// shop.
|
|
379
|
+
/*#__PURE__*/ _jsx(PosHardwareCard, {
|
|
380
|
+
hostId: hostId,
|
|
381
|
+
canManagePos: canManagePos
|
|
382
|
+
}, "hardware-shop")
|
|
351
383
|
]);
|
|
352
384
|
case 'channels':
|
|
353
385
|
case 'integrations':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/commerce-console-page.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 type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport { GridItems } from '@aglyn/shared-ui-jsx'\nimport { HubSections } from '@aglyn/shared-ui-next'\nimport type { ReactNode } from 'react'\nimport {\n COMMERCE_SETTINGS_PAGE_ZONES,\n type CommerceConsoleSectionId,\n type CommerceSettingsSectionId,\n} from './commerce-console-sections'\nimport CatalogOrganizationCard from './console/catalog-organization-card.component'\nimport CommerceAnalyticsCard from './console/commerce-analytics-card.component'\nimport CustomerNotificationsCard from './console/customer-notifications-card.component'\nimport DiscountsCard from './console/discounts-card.component'\nimport GiftCardsCard from './console/gift-cards-card.component'\nimport HostCouponsCard from './console/host-coupons-card.component'\nimport HostOrdersCard from './console/host-orders-card.component'\nimport LocationsCard from './console/locations-card.component'\nimport LocalDeliverySettingsCard from './console/local-delivery-settings-card.component'\nimport PickupDeliveryQueueCard from './console/pickup-delivery-queue-card.component'\nimport MemberPostsCard from './console/member-posts-card.component'\nimport OrderWebhooksCard from './console/order-webhooks-card.component'\nimport PaymentsSettingsCard from './console/payments-settings-card.component'\nimport PosShiftHistoryCard from './console/pos-ops/pos-shift-history-card.component'\nimport PosStaffPinsCard from './console/pos-ops/pos-staff-pins-card.component'\nimport PaymentMethodsCard from './console/payment-methods-card.component'\nimport ProductsHubCard from './console/products-hub-card.component'\nimport RecoveryQueueCard from './console/recovery-queue-card.component'\nimport RegistersCard from './console/registers-card.component'\nimport RegisterHardwareCards from './console/register-hardware-card.component'\nimport PosDevicesCard from './console/pos-devices-card.component'\nimport ReservationsCard from './console/reservations-card.component'\nimport ReturnSettingsCard from './console/return-settings-card.component'\nimport ReturnsCard from './console/returns-card.component'\nimport ReviewsModerationCard from './console/reviews-moderation-card.component'\nimport ReviewSettingsCard from './console/review-settings-card.component'\nimport ShippingSettingsCard from './console/shipping-settings-card.component'\nimport ShipStationCard from './console/shipstation-card.component'\nimport ShippingEasyCard from './console/shippingeasy-card.component'\nimport StockMovementsCard from './console/stock-movements-card.component'\nimport StoreSettingsCard from './console/store-settings-card.component'\nimport StorefrontTaxSummaryCard from './console/storefront-tax-summary-card.component'\nimport SuppliersCard from './console/suppliers-card.component'\nimport TaxSettingsCard from './console/tax-settings-card.component'\nimport { COMMERCE_PROMOTIONS_ZONE } from './console/store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\n\n/**\n * A settings page's zone (AGL-3612, AGL-3713): other plugins' settings for\n * the store — label settings, carrier accounts, a tax service — under the\n * page's own cards. One zone per page, from `COMMERCE_SETTINGS_PAGE_ZONES`;\n * Integrations draws `commerceSettings`, where a widget naming no page lands.\n */\nfunction CommerceSettingsZone(props: {\n hostId: string\n page: CommerceSettingsSectionId\n}) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot\n slot={COMMERCE_SETTINGS_PAGE_ZONES[props.page]}\n hostId={props.hostId}\n orgId={undefined}\n />\n ) : null\n}\n\n/** One settings page: its cards in order, then its zone (AGL-3713). */\nfunction settingsPage(\n page: CommerceSettingsSectionId,\n hostId: string,\n cards: readonly ReactNode[],\n): ReactNode {\n return (\n <GridItems\n spacing={3}\n items={[\n ...cards.map((children) => ({ size: { xs: 12 }, children })),\n {\n size: { xs: 12 },\n children: <CommerceSettingsZone hostId={hostId} page={page} />,\n },\n ]}\n />\n )\n}\n\n/**\n * The `commercePromotions` zone (AGL-3640): other plugins' programs beside\n * the store's own money-off surfaces — a rewards program first.\n */\nfunction CommercePromotionsZone(props: { hostId: string }) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot slot={COMMERCE_PROMOTIONS_ZONE.id} hostId={props.hostId} orgId={undefined} />\n ) : null\n}\n\n/**\n * The body of one commerce section, built only when that section is the one\n * being read (AGL-2501).\n *\n * A function rather than a map of nodes on purpose: a `Record<id, ReactNode>`\n * would CONSTRUCT every section every render, and each card opens its Firestore\n * listens on mount — which is the entire cost this page exists to stop paying.\n * Only the returned branch is ever built.\n */\nfunction sectionBody(\n section: CommerceConsoleSectionId,\n hostId: string,\n canManagePos: boolean,\n): ReactNode {\n switch (section) {\n case 'catalog':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <ProductsHubCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <CatalogOrganizationCard hostId={hostId} />,\n },\n // The ledger every stock writer fills and nothing displayed\n // (AGL-2341). Directly under the catalog, because the question\n // it answers — \"why does this count disagree with the shelf\" —\n // is asked while looking at the count.\n {\n size: { xs: 12 },\n children: <StockMovementsCard hostId={hostId} />,\n },\n { size: { xs: 12 }, children: <MemberPostsCard hostId={hostId} /> },\n ]}\n />\n )\n case 'orders':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <HostOrdersCard hostId={hostId} /> },\n // What to prepare, hand over and drive out (AGL-3624). Renders\n // nothing for a store with no pickup and no local delivery.\n {\n size: { xs: 12 },\n children: <PickupDeliveryQueueCard hostId={hostId} />,\n },\n // The two queues that feed orders rather than record them\n // (AGL-2227): checkouts that stalled and shoppers waiting on\n // stock. Beneath the orders list because both are pre-order.\n {\n size: { xs: 12 },\n children: <RecoveryQueueCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <PosShiftHistoryCard hostId={hostId} />,\n },\n ]}\n />\n )\n case 'returns':\n // Returns (AGL-3611); `?return={id}` opens one on arrival.\n return <ReturnsCard hostId={hostId} />\n case 'promotions':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <DiscountsCard hostId={hostId} /> },\n { size: { xs: 12 }, children: <HostCouponsCard hostId={hostId} /> },\n // Store credit lives with the other money-off surfaces\n // (AGL-2226) — it had no console anywhere before this.\n { size: { xs: 12 }, children: <GiftCardsCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <ReviewsModerationCard hostId={hostId} />,\n },\n // Who may review, and the review-request email (AGL-3736),\n // beside the queue those reviews land in.\n {\n size: { xs: 12 },\n children: <ReviewSettingsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <CommercePromotionsZone hostId={hostId} />,\n },\n ]}\n />\n )\n case 'reservations':\n return <ReservationsCard hostId={hostId} />\n /*\n * The store's settings, a page each (AGL-3713). They were one `settings`\n * section — every card below in one column — and its old address opens\n * Payments (`COMMERCE_RETIRED_SECTIONS`). Each page is its cards, then\n * the zone where other plugins' cards for that page land.\n */\n case 'payments':\n return settingsPage(section, hostId, [\n <PaymentsSettingsCard key=\"payments\" hostId={hostId} />,\n // What shoppers may pay with (AGL-3629), beside the account the\n // money lands in.\n <PaymentMethodsCard key=\"methods\" hostId={hostId} />,\n ])\n case 'checkout':\n return settingsPage(section, hostId, [\n <StoreSettingsCard key=\"store\" hostId={hostId} />,\n // Whether buyers may ask for a return online (AGL-3611): the store's\n // policy, beside the terms and guest-checkout rules above it.\n <ReturnSettingsCard key=\"returns\" hostId={hostId} />,\n ])\n case 'taxes':\n return settingsPage(section, hostId, [\n <TaxSettingsCard key=\"tax\" hostId={hostId} />,\n ])\n case 'shipping':\n return settingsPage(section, hostId, [\n <ShippingSettingsCard key=\"shipping\" hostId={hostId} />,\n // Where parcels ship from, and pickup, per location.\n <LocationsCard key=\"locations\" hostId={hostId} />,\n // The store's own delivery (AGL-3624); pickup is per location, on\n // the Inventory locations card above.\n <LocalDeliverySettingsCard key=\"local\" hostId={hostId} />,\n <SuppliersCard key=\"suppliers\" hostId={hostId} />,\n <ShipStationCard key=\"shipstation\" hostId={hostId} />,\n // ShippingEasy, with the merchant's own keys (AGL-3633).\n <ShippingEasyCard key=\"shippingeasy\" hostId={hostId} />,\n ])\n case 'notifications':\n return settingsPage(section, hostId, [\n <CustomerNotificationsCard key=\"customers\" hostId={hostId} />,\n // The store's own endpoints for order events (AGL-3611). Renders\n // nothing for a person who may not manage them.\n <OrderWebhooksCard key=\"webhooks\" hostId={hostId} />,\n ])\n case 'pos':\n return settingsPage(section, hostId, [\n <RegistersCard key=\"registers\" hostId={hostId} />,\n <PosStaffPinsCard key=\"pins\" hostId={hostId} />,\n // A register's printers, cash drawer and status (AGL-3619), one card\n // per register, after the list that names them.\n <RegisterHardwareCards key=\"hardware\" hostId={hostId} />,\n <PosDevicesCard\n key=\"devices\"\n hostId={hostId}\n canManagePos={canManagePos}\n />,\n ])\n case 'channels':\n case 'integrations':\n // Other plugins' cards only; the rail leaves either page out while\n // its zone has nothing to draw (`onlyWithZones`).\n return settingsPage(section, hostId, [])\n case 'analytics':\n return (\n // Two cards since AGL-2440. The tax summary lives here rather\n // than on the Taxes settings page because that page CONFIGURES tax and\n // this REPORTS what was collected — a merchant reading a figure\n // they may file from should not be one field away from changing\n // the rate that produced it.\n <GridItems\n spacing={3}\n items={[\n {\n size: { xs: 12 },\n children: <CommerceAnalyticsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <StorefrontTaxSummaryCard hostId={hostId} />,\n },\n ]}\n />\n )\n default:\n return null\n }\n}\n\n/**\n * Commerce console page (AGL-395): the Products management surface, owned by\n * the commerce plugin and rendered by the shell's generic plugin route. The\n * product editor's media browser is supplied by the shell's\n * ConsoleMediaPickerProvider (the media library is org/session coupled and\n * stays in the app).\n *\n * ## Sections are ROUTES (AGL-2501)\n *\n * The sections hold thirty-two Firestore listens between them, and a tab\n * strip mounts every panel: opening Catalog also subscribed the orders,\n * promotions, reservations, settings and analytics cards. The `limit()` on\n * those queries is the bill — several ask for 500, and one load reached a\n * ceiling of ~4,460 documents to render one tab.\n *\n * `HubTabs lazy` bought that back as a flag somebody has to remember. A URL\n * per section makes it structural instead: the page builds one section's body\n * and the others do not exist to subscribe. Three things come with it that the\n * tab version faked — a section is linkable, the back button walks sections,\n * and which one is open is a fact about the URL rather than state kept in sync\n * with it. `commerce-console-read-cost.spec.tsx` meters it at the Firestore\n * boundary and refuses a section that listens before it is opened.\n *\n * The shell resolves the section, gates it and hands back the rail's hrefs;\n * this page only has to say what each section contains.\n */\nexport function CommerceConsolePage(props: ConsolePluginPageProps) {\n const { hostId, section, sections, basePath, permissions, hostRole } = props\n /*\n * The register's own gate, for the devices card's Pair display (AGL-3712):\n * `managePos` on a site role that may run it — what the server's\n * `mayWorkRegister` asks. The server stays the enforcement point.\n */\n const canManagePos = permissions?.managePos === true && hostRole?.canPublish === true\n\n /*\n * Nothing, deliberately, while the redirect is in flight.\n *\n * Rendering the default section here instead would issue that section's\n * listens on a URL that is about to be replaced — paying for Catalog on\n * every arrival at `/products`, which is every click of the nav tab.\n */\n if (!section || !sections?.length || !basePath) return null\n\n return (\n <HubSections sections={sections}>\n {sectionBody(section as CommerceConsoleSectionId, hostId, canManagePos)}\n </HubSections>\n )\n}\nCommerceConsolePage.displayName = 'CommerceConsolePage'\n\nexport default CommerceConsolePage\n"],"names":["GridItems","HubSections","COMMERCE_SETTINGS_PAGE_ZONES","CatalogOrganizationCard","CommerceAnalyticsCard","CustomerNotificationsCard","DiscountsCard","GiftCardsCard","HostCouponsCard","HostOrdersCard","LocationsCard","LocalDeliverySettingsCard","PickupDeliveryQueueCard","MemberPostsCard","OrderWebhooksCard","PaymentsSettingsCard","PosShiftHistoryCard","PosStaffPinsCard","PaymentMethodsCard","ProductsHubCard","RecoveryQueueCard","RegistersCard","RegisterHardwareCards","PosDevicesCard","ReservationsCard","ReturnSettingsCard","ReturnsCard","ReviewsModerationCard","ReviewSettingsCard","ShippingSettingsCard","ShipStationCard","ShippingEasyCard","StockMovementsCard","StoreSettingsCard","StorefrontTaxSummaryCard","SuppliersCard","TaxSettingsCard","COMMERCE_PROMOTIONS_ZONE","useConsoleWidgetSlot","CommerceSettingsZone","props","WidgetSlot","slot","page","hostId","orgId","undefined","settingsPage","cards","spacing","items","map","children","size","xs","CommercePromotionsZone","id","sectionBody","section","canManagePos","CommerceConsolePage","sections","basePath","permissions","hostRole","managePos","canPublish","length","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/commerce-console-page.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 type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport { GridItems } from '@aglyn/shared-ui-jsx'\nimport { HubSections } from '@aglyn/shared-ui-next'\nimport type { ReactNode } from 'react'\nimport {\n COMMERCE_SETTINGS_PAGE_ZONES,\n type CommerceConsoleSectionId,\n type CommerceSettingsSectionId,\n} from './commerce-console-sections'\nimport CatalogOrganizationCard from './console/catalog-organization-card.component'\nimport CommerceAnalyticsCard from './console/commerce-analytics-card.component'\nimport CustomerNotificationsCard from './console/customer-notifications-card.component'\nimport DiscountsCard from './console/discounts-card.component'\nimport GiftCardsCard from './console/gift-cards-card.component'\nimport HostCouponsCard from './console/host-coupons-card.component'\nimport HostOrdersCard from './console/host-orders-card.component'\nimport LocationsCard from './console/locations-card.component'\nimport LocalDeliverySettingsCard from './console/local-delivery-settings-card.component'\nimport PickupDeliveryQueueCard from './console/pickup-delivery-queue-card.component'\nimport MemberPostsCard from './console/member-posts-card.component'\nimport OrderWebhooksCard from './console/order-webhooks-card.component'\nimport PaymentsSettingsCard from './console/payments-settings-card.component'\nimport PosCheckInsCard from './console/pos-ops/pos-check-ins-card.component'\nimport PosDayTotalsCard from './console/pos-ops/pos-day-totals-card.component'\nimport PosShiftHistoryCard from './console/pos-ops/pos-shift-history-card.component'\nimport PosStaffPinsCard from './console/pos-ops/pos-staff-pins-card.component'\nimport PaymentMethodsCard from './console/payment-methods-card.component'\nimport ProductsHubCard from './console/products-hub-card.component'\nimport RecoveryQueueCard from './console/recovery-queue-card.component'\nimport RegistersCard from './console/registers-card.component'\nimport RegisterHardwareCards from './console/register-hardware-card.component'\nimport PosDevicesCard from './console/pos-devices-card.component'\nimport PosHardwareCard from './console/pos-hardware-card.component'\nimport ReservationsCard from './console/reservations-card.component'\nimport ReturnSettingsCard from './console/return-settings-card.component'\nimport ReturnsCard from './console/returns-card.component'\nimport ReviewsModerationCard from './console/reviews-moderation-card.component'\nimport ReviewSettingsCard from './console/review-settings-card.component'\nimport ShippingSettingsCard from './console/shipping-settings-card.component'\nimport ShipStationCard from './console/shipstation-card.component'\nimport ShippingEasyCard from './console/shippingeasy-card.component'\nimport StockMovementsCard from './console/stock-movements-card.component'\nimport StoreSettingsCard from './console/store-settings-card.component'\nimport StorefrontTaxSummaryCard from './console/storefront-tax-summary-card.component'\nimport SuppliersCard from './console/suppliers-card.component'\nimport TaxSettingsCard from './console/tax-settings-card.component'\nimport { COMMERCE_PROMOTIONS_ZONE } from './console/store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\n\n/**\n * A settings page's zone (AGL-3612, AGL-3713): other plugins' settings for\n * the store — label settings, carrier accounts, a tax service — under the\n * page's own cards. One zone per page, from `COMMERCE_SETTINGS_PAGE_ZONES`;\n * Integrations draws `commerceSettings`, where a widget naming no page lands.\n */\nfunction CommerceSettingsZone(props: {\n hostId: string\n page: CommerceSettingsSectionId\n}) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot\n slot={COMMERCE_SETTINGS_PAGE_ZONES[props.page]}\n hostId={props.hostId}\n orgId={undefined}\n />\n ) : null\n}\n\n/** One settings page: its cards in order, then its zone (AGL-3713). */\nfunction settingsPage(\n page: CommerceSettingsSectionId,\n hostId: string,\n cards: readonly ReactNode[],\n): ReactNode {\n return (\n <GridItems\n spacing={3}\n items={[\n ...cards.map((children) => ({ size: { xs: 12 }, children })),\n {\n size: { xs: 12 },\n children: <CommerceSettingsZone hostId={hostId} page={page} />,\n },\n ]}\n />\n )\n}\n\n/**\n * The `commercePromotions` zone (AGL-3640): other plugins' programs beside\n * the store's own money-off surfaces — a rewards program first.\n */\nfunction CommercePromotionsZone(props: { hostId: string }) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot slot={COMMERCE_PROMOTIONS_ZONE.id} hostId={props.hostId} orgId={undefined} />\n ) : null\n}\n\n/**\n * The body of one commerce section, built only when that section is the one\n * being read (AGL-2501).\n *\n * A function rather than a map of nodes on purpose: a `Record<id, ReactNode>`\n * would CONSTRUCT every section every render, and each card opens its Firestore\n * listens on mount — which is the entire cost this page exists to stop paying.\n * Only the returned branch is ever built.\n */\nfunction sectionBody(\n section: CommerceConsoleSectionId,\n hostId: string,\n canManagePos: boolean,\n): ReactNode {\n switch (section) {\n case 'catalog':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <ProductsHubCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <CatalogOrganizationCard hostId={hostId} />,\n },\n // The ledger every stock writer fills and nothing displayed\n // (AGL-2341). Directly under the catalog, because the question\n // it answers — \"why does this count disagree with the shelf\" —\n // is asked while looking at the count.\n {\n size: { xs: 12 },\n children: <StockMovementsCard hostId={hostId} />,\n },\n { size: { xs: 12 }, children: <MemberPostsCard hostId={hostId} /> },\n ]}\n />\n )\n case 'orders':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <HostOrdersCard hostId={hostId} /> },\n // What to prepare, hand over and drive out (AGL-3624). Renders\n // nothing for a store with no pickup and no local delivery.\n {\n size: { xs: 12 },\n children: <PickupDeliveryQueueCard hostId={hostId} />,\n },\n // The two queues that feed orders rather than record them\n // (AGL-2227): checkouts that stalled and shoppers waiting on\n // stock. Beneath the orders list because both are pre-order.\n {\n size: { xs: 12 },\n children: <RecoveryQueueCard hostId={hostId} />,\n },\n // One day's or one event's totals across every register, shift\n // and cashier (AGL-4037), above the shifts it adds up.\n {\n size: { xs: 12 },\n children: <PosDayTotalsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n // Who is due at the window and who checked in (AGL-4043), beside\n // the day's totals.\n {\n size: { xs: 12 },\n children: <PosCheckInsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n {\n size: { xs: 12 },\n children: <PosShiftHistoryCard hostId={hostId} />,\n },\n ]}\n />\n )\n case 'returns':\n // Returns (AGL-3611); `?return={id}` opens one on arrival.\n return <ReturnsCard hostId={hostId} />\n case 'promotions':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <DiscountsCard hostId={hostId} /> },\n { size: { xs: 12 }, children: <HostCouponsCard hostId={hostId} /> },\n // Store credit lives with the other money-off surfaces\n // (AGL-2226) — it had no console anywhere before this.\n { size: { xs: 12 }, children: <GiftCardsCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <ReviewsModerationCard hostId={hostId} />,\n },\n // Who may review, and the review-request email (AGL-3736),\n // beside the queue those reviews land in.\n {\n size: { xs: 12 },\n children: <ReviewSettingsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <CommercePromotionsZone hostId={hostId} />,\n },\n ]}\n />\n )\n case 'reservations':\n return <ReservationsCard hostId={hostId} />\n /*\n * The store's settings, a page each (AGL-3713). They were one `settings`\n * section — every card below in one column — and its old address opens\n * Payments (`COMMERCE_RETIRED_SECTIONS`). Each page is its cards, then\n * the zone where other plugins' cards for that page land.\n */\n case 'payments':\n return settingsPage(section, hostId, [\n <PaymentsSettingsCard key=\"payments\" hostId={hostId} />,\n // What shoppers may pay with (AGL-3629), beside the account the\n // money lands in.\n <PaymentMethodsCard key=\"methods\" hostId={hostId} />,\n ])\n case 'checkout':\n return settingsPage(section, hostId, [\n <StoreSettingsCard key=\"store\" hostId={hostId} />,\n // Whether buyers may ask for a return online (AGL-3611): the store's\n // policy, beside the terms and guest-checkout rules above it.\n <ReturnSettingsCard key=\"returns\" hostId={hostId} />,\n ])\n case 'taxes':\n return settingsPage(section, hostId, [\n <TaxSettingsCard key=\"tax\" hostId={hostId} />,\n ])\n case 'shipping':\n return settingsPage(section, hostId, [\n <ShippingSettingsCard key=\"shipping\" hostId={hostId} />,\n // Where parcels ship from, and pickup, per location.\n <LocationsCard key=\"locations\" hostId={hostId} />,\n // The store's own delivery (AGL-3624); pickup is per location, on\n // the Inventory locations card above.\n <LocalDeliverySettingsCard key=\"local\" hostId={hostId} />,\n <SuppliersCard key=\"suppliers\" hostId={hostId} />,\n <ShipStationCard key=\"shipstation\" hostId={hostId} />,\n // ShippingEasy, with the merchant's own keys (AGL-3633).\n <ShippingEasyCard key=\"shippingeasy\" hostId={hostId} />,\n ])\n case 'notifications':\n return settingsPage(section, hostId, [\n <CustomerNotificationsCard key=\"customers\" hostId={hostId} />,\n // The store's own endpoints for order events (AGL-3611). Renders\n // nothing for a person who may not manage them.\n <OrderWebhooksCard key=\"webhooks\" hostId={hostId} />,\n ])\n case 'pos':\n return settingsPage(section, hostId, [\n <RegistersCard key=\"registers\" hostId={hostId} />,\n <PosStaffPinsCard key=\"pins\" hostId={hostId} />,\n // A register's printers, cash drawer and status (AGL-3619), one card\n // per register, after the list that names them.\n <RegisterHardwareCards key=\"hardware\" hostId={hostId} />,\n <PosDevicesCard\n key=\"devices\"\n hostId={hostId}\n canManagePos={canManagePos}\n />,\n // Card readers bought from the platform (AGL-4038), after the card\n // that registers them. Draws nothing until the deployment opens the\n // shop.\n <PosHardwareCard\n key=\"hardware-shop\"\n hostId={hostId}\n canManagePos={canManagePos}\n />,\n ])\n case 'channels':\n case 'integrations':\n // Other plugins' cards only; the rail leaves either page out while\n // its zone has nothing to draw (`onlyWithZones`).\n return settingsPage(section, hostId, [])\n case 'analytics':\n return (\n // Two cards since AGL-2440. The tax summary lives here rather\n // than on the Taxes settings page because that page CONFIGURES tax and\n // this REPORTS what was collected — a merchant reading a figure\n // they may file from should not be one field away from changing\n // the rate that produced it.\n <GridItems\n spacing={3}\n items={[\n {\n size: { xs: 12 },\n children: <CommerceAnalyticsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <StorefrontTaxSummaryCard hostId={hostId} />,\n },\n ]}\n />\n )\n default:\n return null\n }\n}\n\n/**\n * Commerce console page (AGL-395): the Products management surface, owned by\n * the commerce plugin and rendered by the shell's generic plugin route. The\n * product editor's media browser is supplied by the shell's\n * ConsoleMediaPickerProvider (the media library is org/session coupled and\n * stays in the app).\n *\n * ## Sections are ROUTES (AGL-2501)\n *\n * The sections hold thirty-two Firestore listens between them, and a tab\n * strip mounts every panel: opening Catalog also subscribed the orders,\n * promotions, reservations, settings and analytics cards. The `limit()` on\n * those queries is the bill — several ask for 500, and one load reached a\n * ceiling of ~4,460 documents to render one tab.\n *\n * `HubTabs lazy` bought that back as a flag somebody has to remember. A URL\n * per section makes it structural instead: the page builds one section's body\n * and the others do not exist to subscribe. Three things come with it that the\n * tab version faked — a section is linkable, the back button walks sections,\n * and which one is open is a fact about the URL rather than state kept in sync\n * with it. `commerce-console-read-cost.spec.tsx` meters it at the Firestore\n * boundary and refuses a section that listens before it is opened.\n *\n * The shell resolves the section, gates it and hands back the rail's hrefs;\n * this page only has to say what each section contains.\n */\nexport function CommerceConsolePage(props: ConsolePluginPageProps) {\n const { hostId, section, sections, basePath, permissions, hostRole } = props\n /*\n * The register's own gate, for the devices card's Pair display (AGL-3712):\n * `managePos` on a site role that may run it — what the server's\n * `mayWorkRegister` asks. The server stays the enforcement point.\n */\n const canManagePos = permissions?.managePos === true && hostRole?.canPublish === true\n\n /*\n * Nothing, deliberately, while the redirect is in flight.\n *\n * Rendering the default section here instead would issue that section's\n * listens on a URL that is about to be replaced — paying for Catalog on\n * every arrival at `/products`, which is every click of the nav tab.\n */\n if (!section || !sections?.length || !basePath) return null\n\n return (\n <HubSections sections={sections}>\n {sectionBody(section as CommerceConsoleSectionId, hostId, canManagePos)}\n </HubSections>\n )\n}\nCommerceConsolePage.displayName = 'CommerceConsolePage'\n\nexport default CommerceConsolePage\n"],"names":["GridItems","HubSections","COMMERCE_SETTINGS_PAGE_ZONES","CatalogOrganizationCard","CommerceAnalyticsCard","CustomerNotificationsCard","DiscountsCard","GiftCardsCard","HostCouponsCard","HostOrdersCard","LocationsCard","LocalDeliverySettingsCard","PickupDeliveryQueueCard","MemberPostsCard","OrderWebhooksCard","PaymentsSettingsCard","PosCheckInsCard","PosDayTotalsCard","PosShiftHistoryCard","PosStaffPinsCard","PaymentMethodsCard","ProductsHubCard","RecoveryQueueCard","RegistersCard","RegisterHardwareCards","PosDevicesCard","PosHardwareCard","ReservationsCard","ReturnSettingsCard","ReturnsCard","ReviewsModerationCard","ReviewSettingsCard","ShippingSettingsCard","ShipStationCard","ShippingEasyCard","StockMovementsCard","StoreSettingsCard","StorefrontTaxSummaryCard","SuppliersCard","TaxSettingsCard","COMMERCE_PROMOTIONS_ZONE","useConsoleWidgetSlot","CommerceSettingsZone","props","WidgetSlot","slot","page","hostId","orgId","undefined","settingsPage","cards","spacing","items","map","children","size","xs","CommercePromotionsZone","id","sectionBody","section","canManagePos","CommerceConsolePage","sections","basePath","permissions","hostRole","managePos","canPublish","length","displayName"],"mappings":"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"}
|
|
@@ -252,7 +252,7 @@ import { useCommerceEntitlement } from "./entitlement-gate.component.js";
|
|
|
252
252
|
physicalPct > 0 || digitalPct > 0 ? /*#__PURE__*/ _jsx(Typography, {
|
|
253
253
|
variant: "body2",
|
|
254
254
|
color: "text.secondary",
|
|
255
|
-
children: '
|
|
255
|
+
children: 'At the register, cash, gift card and store credit payments ' + 'carry no fee. On card payments it is deducted from your ' + 'Stripe payout; on room-charge payments there is no payout to ' + 'deduct from, so it is added to your monthly ' + `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} invoice instead.`
|
|
256
256
|
}) : null
|
|
257
257
|
]
|
|
258
258
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/payments-settings-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 { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport * as Aglyn from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Alert, Button, Chip, Stack, Typography } from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport { useOrgPlan } from '@aglyn/tenant-feature-instance'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useCommerceEntitlement } from './entitlement-gate.component'\n\nexport interface PaymentsSettingsCardProps {\n hostId: string\n}\n\n/** The element id the Payments card carries, for a link on the same page that lands on it (AGL-3982). */\nexport const PAYMENTS_SETTINGS_ANCHOR = 'store-payments'\n\n/**\n * Merchant payments card (AGL-284): Stripe Connect Express onboarding\n * status for the org owner + the plan's transaction-fee ladder so the\n * \"upgrade to kill fees\" motion (AGL-278) is visible where it matters.\n */\nexport function PaymentsSettingsCard(props: PaymentsSettingsCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n /**\n * A one-time Stripe Express dashboard link, minted by the connect route on\n * request. Not persisted: login links are single-use and short-lived, so a\n * stored one would be a button that fails the second time it is pressed.\n */\n const [dashboardUrl, setDashboardUrl] = useState<string | null>(null)\n const { org, ready: planReady } = useOrgPlan(hostId)\n /** Bumped by Retry to re-subscribe the profile listen (AGL-1380). */\n const [retryNonce, setRetryNonce] = useState(0)\n const { upgradeHref } = useCommerceEntitlement(hostId, 'commerce')\n /**\n * The OWNER's profile: the Stripe account every money route charges\n * against is the one on the workspace owner's profile. Reading the\n * signed-in member's instead told an admin who is not the owner that a\n * connected store was not set up.\n */\n const ownerUid =\n typeof org?.ownerUid === 'string' && org.ownerUid ? org.ownerUid : undefined\n const { data: profile, status: profileStatus } = useFirestoreDoc<any>(\n // Held at null rather than addressed as `profiles/-pending-` — that\n // sentinel issued a guaranteed-denied read on every pre-auth mount, and\n // a denial lands in `status: 'error'`, which now means something.\n () => (ownerUid ? doc(firestore, 'profiles', ownerUid) : null),\n [firestore, ownerUid, retryNonce],\n )\n const isOwner = Boolean(\n org?.ownerUid && (user as any)?.uid === org.ownerUid,\n )\n /**\n * Three outcomes, not two (AGL-1380). An absent profile doc is the value\n * BEFORE an answer as much as it is the value of a merchant who never\n * connected Stripe, so \"Not set up\" off a falsy `stripeChargesEnabled` is a\n * claim about this org's payment setup made without having heard back. It\n * is wrong in the direction that provokes action: the same falsy value\n * turns the button into \"Set up payments\", which sends a merchant who is\n * already taking money into Stripe onboarding.\n */\n const stripeState: 'pending' | 'error' | 'loaded' =\n !planReady || (ownerUid && profileStatus === 'loading')\n ? 'pending'\n : profileStatus === 'error'\n ? 'error'\n : 'loaded'\n /**\n * WHICH STRIPE WORLD THE STORED ACCOUNT BELONGS TO (AGL-2471).\n *\n * `stripeChargesEnabled: true` was the whole readiness claim, and a\n * production profile carrying it named a TEST-mode account: this card said\n * \"Charges enabled\" about three storefronts that could not take a single\n * payment. Only a literal boolean counts as recorded — the same\n * three-valued reading `merchantAccountIsReady` uses on the server, so the\n * chip and the checkout cannot disagree.\n */\n const modeVerified = typeof profile?.stripeAccountLivemode === 'boolean'\n const chargesConnected =\n stripeState === 'loaded' && Boolean(profile?.stripeChargesEnabled)\n const modeUnverified = chargesConnected && !modeVerified\n const chargesEnabled = chargesConnected && modeVerified\n const physicalPct = Aglyn.resolveTransactionFeePct(org, 'physical')\n const digitalPct = Aglyn.resolveTransactionFeePct(org, 'digital')\n const commerceEnabled = Aglyn.checkEntitlement(org, 'commerce')\n\n const handleConnect = useCallback(async () => {\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/commerce/connect', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId }),\n })\n const payload = await response.json()\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'Payments are not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'Payment setup failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n if (payload.chargesEnabled) {\n // \"% who connect Stripe\" — a GTM plan §6 activation metric\n // (AGL-1561). Gated on the TRANSITION, not the state: this handler\n // is a re-entrant create-or-resume, so it answers `chargesEnabled:\n // true` on every subsequent visit to a connected account, and a bare\n // event here would count one merchant once per click forever.\n // `chargesEnabled` is the state read from the profile BEFORE this\n // request, so the event fires only when onboarding actually completed.\n if (!chargesEnabled) trackEvent('stripe_connected', {})\n // CHARGES AND PAYOUTS ARE TWO FLAGS, AND ONLY ONE OF THEM IS THIS\n // SENTENCE (AGL-1997). `chargesEnabled` says Stripe will let the\n // account take money; whether the money can LEAVE is `payoutsEnabled`,\n // which the route answers alongside it. Charges-yes/payouts-no is an\n // ordinary Stripe state — verification pending or lapsed, no payout\n // method — and announcing \"Payments are enabled\" in it is false in the\n // direction that costs the merchant: they sell believing they are\n // paid, and the funds sit in a Connect account that cannot release\n // them. Read three-valued, so only a literal `false` from Stripe\n // downgrades the claim; an absent flag means unasked, not off.\n const payoutsBlocked = payload.payoutsEnabled === false\n // A WARNING THAT NAMES A PROBLEM MUST OFFER THE FIX.\n //\n // Stripe is the only place payouts can be released — an Express\n // account has no password and no direct login — so telling the\n // merchant their funds are stranded and then keeping them here is half\n // an answer. The route now mints the remediation link for exactly this\n // state; going there is the whole point of pressing the button.\n if (payoutsBlocked && payload.url) {\n return void window.location.assign(payload.url)\n }\n // Payouts are flowing, so the link is the Express dashboard: balance,\n // payout schedule, and the reason a payout failed. Held in state\n // rather than followed, because this click was a status check and\n // navigating away from one nobody asked to leave is its own defect.\n if (!payoutsBlocked && typeof payload.dashboardUrl === 'string') {\n setDashboardUrl(payload.dashboardUrl)\n }\n return void enqueueSnackbar(\n payoutsBlocked\n ? 'Connected — payouts are not released yet'\n : 'Payments are enabled',\n {\n variant: payoutsBlocked ? 'warning' : 'success',\n persist: false,\n },\n )\n }\n if (payload.url) window.location.assign(payload.url)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [user, hostId, chargesEnabled, enqueueSnackbar])\n\n return (\n <CardDisplay\n id={PAYMENTS_SETTINGS_ANCHOR}\n header={'Payments'}\n help={pluginDocsHelp('commerceEndToEnd', {\n anchor: '#1-connect-payments',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {'Stripe account'}\n </Typography>\n {/*\n No chip at all on error: both labels it could carry — \"Charges\n enabled\" and \"Not set up\" — assert something we failed to find\n out. Whatever Stripe is doing right now it carries on doing.\n */}\n {stripeState === 'error' ? null : (\n <Chip\n size=\"small\"\n label={\n stripeState === 'pending'\n ? 'Checking…'\n : chargesEnabled\n ? 'Charges enabled'\n : modeUnverified\n ? 'Not verified'\n : 'Not set up'\n }\n color={\n stripeState === 'pending'\n ? 'default'\n : chargesEnabled\n ? 'success'\n : modeUnverified\n ? 'error'\n : 'warning'\n }\n variant=\"outlined\"\n />\n )}\n </Stack>\n {stripeState === 'error' ? (\n <Alert\n severity=\"error\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n onClick={() => setRetryNonce((n) => n + 1)}\n >\n {'Retry'}\n </Button>\n }\n >\n {'We couldn’t load your payment setup. This says nothing about ' +\n 'whether payments are on — we could not reach the setting to ' +\n 'find out. Nothing has changed.'}\n </Alert>\n ) : null}\n {/*\n Every line below reads the plan, and an org doc still in flight\n resolves to the FREE tier (AGL-1064) — which would flash \"Selling\n requires a paid plan\" and the wrong fee percentages at a paying\n seller, then correct itself. Say nothing until it is known.\n */}\n {!planReady ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your plan…'}\n </Typography>\n ) : (\n <>\n {!commerceEnabled ? (\n <PrerequisiteNotice href={upgradeHref} actionLabel=\"See plans\">\n {'Selling needs a paid plan. Choose one on Billing, then connect Stripe here.'}\n </PrerequisiteNotice>\n ) : null}\n {/*\n THE LEGAL NAME, not the org's resolved `productName`\n (AGL-2351). This sentence says who takes money off the\n merchant's own Stripe account, and the application fee lands in\n the platform Stripe account — held by the operating entity, not\n by a white-label agency reselling the console. Naming the\n agency here would assert a fee relationship that does not\n exist. `PLATFORM_BRAND_LEGAL_NAME` still configures cleanly for\n a self-host operator, who really is the entity collecting it.\n */}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Buyers pay on your own Stripe account; ' +\n `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} collects a platform fee ` +\n 'per sale based on your plan:'}\n </Typography>\n {/* The DIGITAL rate is not products-only (AGL-2315). A paid\n booking is a service sale and resolves through the same\n `'service'`/digital axis, so a bookings-only merchant pays this\n exact number — and this card was the one place they could read\n their own rate while naming only \"products\". Stated here rather\n than adding a third figure: it is one rate, not two. */}\n <Typography variant=\"body2\">\n {`Physical products: ${physicalPct}% · Digital products, ` +\n `services & bookings: ${digitalPct}%`}\n {physicalPct > 0 || digitalPct > 0 ? (\n <Typography\n component=\"span\"\n variant=\"caption\"\n color=\"text.secondary\"\n >\n {' — higher plans reduce fees to 0%'}\n </Typography>\n ) : null}\n </Typography>\n {/* CARD PROCESSING, PASSED THROUGH AT COST (AGL-2152).\n\n Unconditional, including on the 0% plans, because it is\n exactly those plans where the merchant would otherwise read\n \"0%\" and be surprised by a deduction. Their PLATFORM fee\n really is zero — the figure below is Stripe's own charge for\n taking the payment, which every storefront sale incurs and\n which used to be absorbed silently out of the platform's\n balance rather than passed through.\n\n Named as a range rather than one number because the buyer\n chooses the payment method after the session is created:\n cards settle at the low end, buy-now-pay-later at the high\n end, and the deduction is sized for the dearest so a sale can\n never cost more to process than it collects. */}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Card processing is passed through at cost on top of that: ' +\n `${Aglyn.CARD_PROCESSING_PERCENT}–` +\n `${Aglyn.BNPL_PROCESSING_PERCENT}% + ` +\n `${Aglyn.PROCESSING_FIXED_CENTS}¢ per online ` +\n 'sale, what Stripe charges to take the payment. It is not a ' +\n `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} margin.`}\n </Typography>\n {/* EVERY TENDER, AND HOW EACH IS COLLECTED (AGL-2111).\n\n Until now this card said \"per sale\" and meant it for online and\n card sales only: cash and room-charge sales at the register\n recorded no fee at all, so a merchant could read this sentence,\n ring everything as cash, and pay nothing. The fee now attaches\n to the sale on every tender, which makes the sentence above\n true — and creates a second, visible collection route the\n merchant has to be told about BEFORE it appears on their\n invoice, because it is money leaving by a door they have never\n seen it leave by.\n\n Shown only when a rate actually applies: on a 0% plan there is\n nothing to collect either way, and the paragraph would be noise\n on the card of the merchants who upgraded to escape fees. */}\n {physicalPct > 0 || digitalPct > 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'The fee is charged on the sale, not on how it was paid — ' +\n 'in-person cash and room-charge sales carry it too. On card ' +\n 'sales it is deducted from your Stripe payout; on cash and ' +\n 'room-charge sales there is no payout to deduct from, so it ' +\n `is added to your monthly ${Aglyn.PLATFORM_BRAND_LEGAL_NAME} ` +\n 'invoice instead.'}\n </Typography>\n ) : null}\n </>\n )}\n {/*\n AGL-2471: connected, and refused by every money door because the\n account was never verified against this deployment's Stripe mode.\n \"Not set up\" would be a lie in the other direction — the merchant\n did set something up — so the card names what is actually wrong and\n what to do about it.\n */}\n {modeUnverified ? (\n <Alert severity=\"error\">\n {'Your Stripe account has not been verified for payments on ' +\n 'this site, so sales will be refused. Set up payments again ' +\n 'to verify it — if it was connected against Stripe test mode, ' +\n 'you will need to connect a live account.'}\n </Alert>\n ) : null}\n {/*\n The button's own label is a claim — \"Set up payments\" tells the\n owner they have none. Withheld until the answer is in, for the same\n reason as the chip (AGL-1380); on error the Retry above is the only\n action offered, because acting on a setup we could not read is how\n a connected merchant gets sent back through onboarding.\n */}\n {/*\n WHERE THE MONEY STOPPED. Mirrored onto this profile by the\n `payout.failed` handler and retired by the next successful payout, so\n it names a live problem rather than a scar. Without it a merchant sold\n into an account that could not release the funds and the card said\n \"Payments are enabled\" the whole time — the storefront looked healthy\n from every angle available to them.\n */}\n {stripeState === 'loaded' && profile?.lastPayoutFailureAtMs ? (\n <Alert severity=\"warning\" variant=\"outlined\">\n {`A payout of $${(\n Number(profile.lastPayoutFailureCents ?? 0) / 100\n ).toFixed(2)} did not reach your bank on ${new Date(\n Number(profile.lastPayoutFailureAtMs),\n ).toLocaleDateString()} — ${String(\n profile.lastPayoutFailureReason ?? 'Stripe did not say why',\n )} The money is still in your Stripe account. Open Stripe to fix your payout details.`}\n </Alert>\n ) : null}\n {!planReady || stripeState !== 'loaded' ? null : isOwner ? (\n <>\n <Button\n size=\"small\"\n variant={chargesEnabled ? 'text' : 'contained'}\n color=\"primary\"\n disabled={busy}\n onClick={handleConnect}\n sx={{ alignSelf: 'flex-start' }}\n >\n {chargesEnabled\n ? 'Refresh status'\n : busy\n ? 'Opening Stripe…'\n : 'Set up payments'}\n </Button>\n {/*\n Where the money actually is. Aglyn records none of it —\n no balance, no payout schedule, and no `payout.failed` handling\n anywhere — so a merchant whose payout bounced has no way to learn\n that from this console. An Express account has no direct login\n either, which leaves a link minted by the platform as the only\n route in. `target=\"_blank\"` because it leaves the app entirely.\n */}\n {dashboardUrl ? (\n <Button\n size=\"small\"\n variant=\"text\"\n color=\"primary\"\n href={dashboardUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n sx={{ alignSelf: 'flex-start' }}\n >\n {'View payouts in Stripe'}\n </Button>\n ) : null}\n </>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Only the organization owner can set up payments.'}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n )\n}\nPaymentsSettingsCard.displayName = 'PaymentsSettingsCard'\n\nexport default PaymentsSettingsCard\n"],"names":["trackEvent","Aglyn","CardDisplay","useSnackbar","Alert","Button","Chip","Stack","Typography","doc","useCallback","useState","useFirestore","useUser","useFirestoreDoc","useOrgPlan","pluginDocsHelp","authorizedFetch","PrerequisiteNotice","useCommerceEntitlement","PAYMENTS_SETTINGS_ANCHOR","PaymentsSettingsCard","props","profile","hostId","firestore","data","user","enqueueSnackbar","busy","setBusy","dashboardUrl","setDashboardUrl","org","ready","planReady","retryNonce","setRetryNonce","upgradeHref","ownerUid","undefined","status","profileStatus","isOwner","Boolean","uid","stripeState","modeVerified","stripeAccountLivemode","chargesConnected","stripeChargesEnabled","modeUnverified","chargesEnabled","physicalPct","resolveTransactionFeePct","digitalPct","commerceEnabled","checkEntitlement","handleConnect","response","method","headers","body","JSON","stringify","payload","json","variant","persist","ok","error","allowDuplicate","payoutsBlocked","payoutsEnabled","url","window","location","assign","console","id","header","help","anchor","contentGutterX","contentGutterY","spacing","direction","sx","alignItems","flex","size","label","color","severity","action","onClick","n","href","actionLabel","PLATFORM_BRAND_LEGAL_NAME","component","CARD_PROCESSING_PERCENT","BNPL_PROCESSING_PERCENT","PROCESSING_FIXED_CENTS","lastPayoutFailureAtMs","Number","lastPayoutFailureCents","toFixed","Date","toLocaleDateString","String","lastPayoutFailureReason","disabled","alignSelf","target","rel","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/payments-settings-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 { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport * as Aglyn from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Alert, Button, Chip, Stack, Typography } from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport { useOrgPlan } from '@aglyn/tenant-feature-instance'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useCommerceEntitlement } from './entitlement-gate.component'\n\nexport interface PaymentsSettingsCardProps {\n hostId: string\n}\n\n/** The element id the Payments card carries, for a link on the same page that lands on it (AGL-3982). */\nexport const PAYMENTS_SETTINGS_ANCHOR = 'store-payments'\n\n/**\n * Merchant payments card (AGL-284): Stripe Connect Express onboarding\n * status for the org owner + the plan's transaction-fee ladder so the\n * \"upgrade to kill fees\" motion (AGL-278) is visible where it matters.\n */\nexport function PaymentsSettingsCard(props: PaymentsSettingsCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n /**\n * A one-time Stripe Express dashboard link, minted by the connect route on\n * request. Not persisted: login links are single-use and short-lived, so a\n * stored one would be a button that fails the second time it is pressed.\n */\n const [dashboardUrl, setDashboardUrl] = useState<string | null>(null)\n const { org, ready: planReady } = useOrgPlan(hostId)\n /** Bumped by Retry to re-subscribe the profile listen (AGL-1380). */\n const [retryNonce, setRetryNonce] = useState(0)\n const { upgradeHref } = useCommerceEntitlement(hostId, 'commerce')\n /**\n * The OWNER's profile: the Stripe account every money route charges\n * against is the one on the workspace owner's profile. Reading the\n * signed-in member's instead told an admin who is not the owner that a\n * connected store was not set up.\n */\n const ownerUid =\n typeof org?.ownerUid === 'string' && org.ownerUid ? org.ownerUid : undefined\n const { data: profile, status: profileStatus } = useFirestoreDoc<any>(\n // Held at null rather than addressed as `profiles/-pending-` — that\n // sentinel issued a guaranteed-denied read on every pre-auth mount, and\n // a denial lands in `status: 'error'`, which now means something.\n () => (ownerUid ? doc(firestore, 'profiles', ownerUid) : null),\n [firestore, ownerUid, retryNonce],\n )\n const isOwner = Boolean(\n org?.ownerUid && (user as any)?.uid === org.ownerUid,\n )\n /**\n * Three outcomes, not two (AGL-1380). An absent profile doc is the value\n * BEFORE an answer as much as it is the value of a merchant who never\n * connected Stripe, so \"Not set up\" off a falsy `stripeChargesEnabled` is a\n * claim about this org's payment setup made without having heard back. It\n * is wrong in the direction that provokes action: the same falsy value\n * turns the button into \"Set up payments\", which sends a merchant who is\n * already taking money into Stripe onboarding.\n */\n const stripeState: 'pending' | 'error' | 'loaded' =\n !planReady || (ownerUid && profileStatus === 'loading')\n ? 'pending'\n : profileStatus === 'error'\n ? 'error'\n : 'loaded'\n /**\n * WHICH STRIPE WORLD THE STORED ACCOUNT BELONGS TO (AGL-2471).\n *\n * `stripeChargesEnabled: true` was the whole readiness claim, and a\n * production profile carrying it named a TEST-mode account: this card said\n * \"Charges enabled\" about three storefronts that could not take a single\n * payment. Only a literal boolean counts as recorded — the same\n * three-valued reading `merchantAccountIsReady` uses on the server, so the\n * chip and the checkout cannot disagree.\n */\n const modeVerified = typeof profile?.stripeAccountLivemode === 'boolean'\n const chargesConnected =\n stripeState === 'loaded' && Boolean(profile?.stripeChargesEnabled)\n const modeUnverified = chargesConnected && !modeVerified\n const chargesEnabled = chargesConnected && modeVerified\n const physicalPct = Aglyn.resolveTransactionFeePct(org, 'physical')\n const digitalPct = Aglyn.resolveTransactionFeePct(org, 'digital')\n const commerceEnabled = Aglyn.checkEntitlement(org, 'commerce')\n\n const handleConnect = useCallback(async () => {\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/commerce/connect', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId }),\n })\n const payload = await response.json()\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'Payments are not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'Payment setup failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n if (payload.chargesEnabled) {\n // \"% who connect Stripe\" — a GTM plan §6 activation metric\n // (AGL-1561). Gated on the TRANSITION, not the state: this handler\n // is a re-entrant create-or-resume, so it answers `chargesEnabled:\n // true` on every subsequent visit to a connected account, and a bare\n // event here would count one merchant once per click forever.\n // `chargesEnabled` is the state read from the profile BEFORE this\n // request, so the event fires only when onboarding actually completed.\n if (!chargesEnabled) trackEvent('stripe_connected', {})\n // CHARGES AND PAYOUTS ARE TWO FLAGS, AND ONLY ONE OF THEM IS THIS\n // SENTENCE (AGL-1997). `chargesEnabled` says Stripe will let the\n // account take money; whether the money can LEAVE is `payoutsEnabled`,\n // which the route answers alongside it. Charges-yes/payouts-no is an\n // ordinary Stripe state — verification pending or lapsed, no payout\n // method — and announcing \"Payments are enabled\" in it is false in the\n // direction that costs the merchant: they sell believing they are\n // paid, and the funds sit in a Connect account that cannot release\n // them. Read three-valued, so only a literal `false` from Stripe\n // downgrades the claim; an absent flag means unasked, not off.\n const payoutsBlocked = payload.payoutsEnabled === false\n // A WARNING THAT NAMES A PROBLEM MUST OFFER THE FIX.\n //\n // Stripe is the only place payouts can be released — an Express\n // account has no password and no direct login — so telling the\n // merchant their funds are stranded and then keeping them here is half\n // an answer. The route now mints the remediation link for exactly this\n // state; going there is the whole point of pressing the button.\n if (payoutsBlocked && payload.url) {\n return void window.location.assign(payload.url)\n }\n // Payouts are flowing, so the link is the Express dashboard: balance,\n // payout schedule, and the reason a payout failed. Held in state\n // rather than followed, because this click was a status check and\n // navigating away from one nobody asked to leave is its own defect.\n if (!payoutsBlocked && typeof payload.dashboardUrl === 'string') {\n setDashboardUrl(payload.dashboardUrl)\n }\n return void enqueueSnackbar(\n payoutsBlocked\n ? 'Connected — payouts are not released yet'\n : 'Payments are enabled',\n {\n variant: payoutsBlocked ? 'warning' : 'success',\n persist: false,\n },\n )\n }\n if (payload.url) window.location.assign(payload.url)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [user, hostId, chargesEnabled, enqueueSnackbar])\n\n return (\n <CardDisplay\n id={PAYMENTS_SETTINGS_ANCHOR}\n header={'Payments'}\n help={pluginDocsHelp('commerceEndToEnd', {\n anchor: '#1-connect-payments',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {'Stripe account'}\n </Typography>\n {/*\n No chip at all on error: both labels it could carry — \"Charges\n enabled\" and \"Not set up\" — assert something we failed to find\n out. Whatever Stripe is doing right now it carries on doing.\n */}\n {stripeState === 'error' ? null : (\n <Chip\n size=\"small\"\n label={\n stripeState === 'pending'\n ? 'Checking…'\n : chargesEnabled\n ? 'Charges enabled'\n : modeUnverified\n ? 'Not verified'\n : 'Not set up'\n }\n color={\n stripeState === 'pending'\n ? 'default'\n : chargesEnabled\n ? 'success'\n : modeUnverified\n ? 'error'\n : 'warning'\n }\n variant=\"outlined\"\n />\n )}\n </Stack>\n {stripeState === 'error' ? (\n <Alert\n severity=\"error\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n onClick={() => setRetryNonce((n) => n + 1)}\n >\n {'Retry'}\n </Button>\n }\n >\n {'We couldn’t load your payment setup. This says nothing about ' +\n 'whether payments are on — we could not reach the setting to ' +\n 'find out. Nothing has changed.'}\n </Alert>\n ) : null}\n {/*\n Every line below reads the plan, and an org doc still in flight\n resolves to the FREE tier (AGL-1064) — which would flash \"Selling\n requires a paid plan\" and the wrong fee percentages at a paying\n seller, then correct itself. Say nothing until it is known.\n */}\n {!planReady ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your plan…'}\n </Typography>\n ) : (\n <>\n {!commerceEnabled ? (\n <PrerequisiteNotice href={upgradeHref} actionLabel=\"See plans\">\n {'Selling needs a paid plan. Choose one on Billing, then connect Stripe here.'}\n </PrerequisiteNotice>\n ) : null}\n {/*\n THE LEGAL NAME, not the org's resolved `productName`\n (AGL-2351). This sentence says who takes money off the\n merchant's own Stripe account, and the application fee lands in\n the platform Stripe account — held by the operating entity, not\n by a white-label agency reselling the console. Naming the\n agency here would assert a fee relationship that does not\n exist. `PLATFORM_BRAND_LEGAL_NAME` still configures cleanly for\n a self-host operator, who really is the entity collecting it.\n */}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Buyers pay on your own Stripe account; ' +\n `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} collects a platform fee ` +\n 'per sale based on your plan:'}\n </Typography>\n {/* The DIGITAL rate is not products-only (AGL-2315). A paid\n booking is a service sale and resolves through the same\n `'service'`/digital axis, so a bookings-only merchant pays this\n exact number — and this card was the one place they could read\n their own rate while naming only \"products\". Stated here rather\n than adding a third figure: it is one rate, not two. */}\n <Typography variant=\"body2\">\n {`Physical products: ${physicalPct}% · Digital products, ` +\n `services & bookings: ${digitalPct}%`}\n {physicalPct > 0 || digitalPct > 0 ? (\n <Typography\n component=\"span\"\n variant=\"caption\"\n color=\"text.secondary\"\n >\n {' — higher plans reduce fees to 0%'}\n </Typography>\n ) : null}\n </Typography>\n {/* CARD PROCESSING, PASSED THROUGH AT COST (AGL-2152).\n\n Unconditional, including on the 0% plans, because it is\n exactly those plans where the merchant would otherwise read\n \"0%\" and be surprised by a deduction. Their PLATFORM fee\n really is zero — the figure below is Stripe's own charge for\n taking the payment, which every storefront sale incurs and\n which used to be absorbed silently out of the platform's\n balance rather than passed through.\n\n Named as a range rather than one number because the buyer\n chooses the payment method after the session is created:\n cards settle at the low end, buy-now-pay-later at the high\n end, and the deduction is sized for the dearest so a sale can\n never cost more to process than it collects. */}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Card processing is passed through at cost on top of that: ' +\n `${Aglyn.CARD_PROCESSING_PERCENT}–` +\n `${Aglyn.BNPL_PROCESSING_PERCENT}% + ` +\n `${Aglyn.PROCESSING_FIXED_CENTS}¢ per online ` +\n 'sale, what Stripe charges to take the payment. It is not a ' +\n `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} margin.`}\n </Typography>\n {/* WHICH REGISTER TENDERS CARRY THE FEE, AND HOW EACH IS\n COLLECTED (AGL-2111, AGL-4036).\n\n Card and room-charge payments at the register carry the fee;\n cash, gift cards and store credit carry none\n (`CommerceModel.paymentCarriesPlatformFee`). A room charge's\n fee leaves by a door the merchant has never seen money leave\n by, their monthly invoice, so it is said here BEFORE it\n appears there.\n\n Shown only when a rate actually applies: on a 0% plan there is\n nothing to collect either way, and the paragraph would be noise\n on the card of the merchants who upgraded to escape fees. */}\n {physicalPct > 0 || digitalPct > 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'At the register, cash, gift card and store credit payments ' +\n 'carry no fee. On card payments it is deducted from your ' +\n 'Stripe payout; on room-charge payments there is no payout to ' +\n 'deduct from, so it is added to your monthly ' +\n `${Aglyn.PLATFORM_BRAND_LEGAL_NAME} invoice instead.`}\n </Typography>\n ) : null}\n </>\n )}\n {/*\n AGL-2471: connected, and refused by every money door because the\n account was never verified against this deployment's Stripe mode.\n \"Not set up\" would be a lie in the other direction — the merchant\n did set something up — so the card names what is actually wrong and\n what to do about it.\n */}\n {modeUnverified ? (\n <Alert severity=\"error\">\n {'Your Stripe account has not been verified for payments on ' +\n 'this site, so sales will be refused. Set up payments again ' +\n 'to verify it — if it was connected against Stripe test mode, ' +\n 'you will need to connect a live account.'}\n </Alert>\n ) : null}\n {/*\n The button's own label is a claim — \"Set up payments\" tells the\n owner they have none. Withheld until the answer is in, for the same\n reason as the chip (AGL-1380); on error the Retry above is the only\n action offered, because acting on a setup we could not read is how\n a connected merchant gets sent back through onboarding.\n */}\n {/*\n WHERE THE MONEY STOPPED. Mirrored onto this profile by the\n `payout.failed` handler and retired by the next successful payout, so\n it names a live problem rather than a scar. Without it a merchant sold\n into an account that could not release the funds and the card said\n \"Payments are enabled\" the whole time — the storefront looked healthy\n from every angle available to them.\n */}\n {stripeState === 'loaded' && profile?.lastPayoutFailureAtMs ? (\n <Alert severity=\"warning\" variant=\"outlined\">\n {`A payout of $${(\n Number(profile.lastPayoutFailureCents ?? 0) / 100\n ).toFixed(2)} did not reach your bank on ${new Date(\n Number(profile.lastPayoutFailureAtMs),\n ).toLocaleDateString()} — ${String(\n profile.lastPayoutFailureReason ?? 'Stripe did not say why',\n )} The money is still in your Stripe account. Open Stripe to fix your payout details.`}\n </Alert>\n ) : null}\n {!planReady || stripeState !== 'loaded' ? null : isOwner ? (\n <>\n <Button\n size=\"small\"\n variant={chargesEnabled ? 'text' : 'contained'}\n color=\"primary\"\n disabled={busy}\n onClick={handleConnect}\n sx={{ alignSelf: 'flex-start' }}\n >\n {chargesEnabled\n ? 'Refresh status'\n : busy\n ? 'Opening Stripe…'\n : 'Set up payments'}\n </Button>\n {/*\n Where the money actually is. Aglyn records none of it —\n no balance, no payout schedule, and no `payout.failed` handling\n anywhere — so a merchant whose payout bounced has no way to learn\n that from this console. An Express account has no direct login\n either, which leaves a link minted by the platform as the only\n route in. `target=\"_blank\"` because it leaves the app entirely.\n */}\n {dashboardUrl ? (\n <Button\n size=\"small\"\n variant=\"text\"\n color=\"primary\"\n href={dashboardUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n sx={{ alignSelf: 'flex-start' }}\n >\n {'View payouts in Stripe'}\n </Button>\n ) : null}\n </>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Only the organization owner can set up payments.'}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n )\n}\nPaymentsSettingsCard.displayName = 'PaymentsSettingsCard'\n\nexport default PaymentsSettingsCard\n"],"names":["trackEvent","Aglyn","CardDisplay","useSnackbar","Alert","Button","Chip","Stack","Typography","doc","useCallback","useState","useFirestore","useUser","useFirestoreDoc","useOrgPlan","pluginDocsHelp","authorizedFetch","PrerequisiteNotice","useCommerceEntitlement","PAYMENTS_SETTINGS_ANCHOR","PaymentsSettingsCard","props","profile","hostId","firestore","data","user","enqueueSnackbar","busy","setBusy","dashboardUrl","setDashboardUrl","org","ready","planReady","retryNonce","setRetryNonce","upgradeHref","ownerUid","undefined","status","profileStatus","isOwner","Boolean","uid","stripeState","modeVerified","stripeAccountLivemode","chargesConnected","stripeChargesEnabled","modeUnverified","chargesEnabled","physicalPct","resolveTransactionFeePct","digitalPct","commerceEnabled","checkEntitlement","handleConnect","response","method","headers","body","JSON","stringify","payload","json","variant","persist","ok","error","allowDuplicate","payoutsBlocked","payoutsEnabled","url","window","location","assign","console","id","header","help","anchor","contentGutterX","contentGutterY","spacing","direction","sx","alignItems","flex","size","label","color","severity","action","onClick","n","href","actionLabel","PLATFORM_BRAND_LEGAL_NAME","component","CARD_PROCESSING_PERCENT","BNPL_PROCESSING_PERCENT","PROCESSING_FIXED_CENTS","lastPayoutFailureAtMs","Number","lastPayoutFailureCents","toFixed","Date","toLocaleDateString","String","lastPayoutFailureReason","disabled","alignSelf","target","rel","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { authorizedFetch } from '@aglyn/shared-util-http/authorized-token';
|
|
18
|
+
import type { PosHardwareLine, PosHardwareOffer, PosHardwareOrderStatus, PosHardwareShippingMethod, PosHardwareTracking } from '../../../model/pos-hardware';
|
|
19
|
+
type User = Parameters<typeof authorizedFetch>[0];
|
|
20
|
+
export declare class PosHardwareRequestError extends Error {
|
|
21
|
+
readonly status: number;
|
|
22
|
+
constructor(message: string, status: number);
|
|
23
|
+
}
|
|
24
|
+
export type PosHardwareCatalog = {
|
|
25
|
+
available: false;
|
|
26
|
+
} | {
|
|
27
|
+
available: true;
|
|
28
|
+
offers: PosHardwareOffer[];
|
|
29
|
+
shipping: Array<{
|
|
30
|
+
method: PosHardwareShippingMethod;
|
|
31
|
+
label: string;
|
|
32
|
+
cents: number;
|
|
33
|
+
}>;
|
|
34
|
+
automaticTax: boolean;
|
|
35
|
+
shipCountries: string[];
|
|
36
|
+
};
|
|
37
|
+
/** An order as the Hardware card lists it. */
|
|
38
|
+
export interface PosHardwareOrderRow {
|
|
39
|
+
id: string;
|
|
40
|
+
number: string;
|
|
41
|
+
status: PosHardwareOrderStatus;
|
|
42
|
+
lines: PosHardwareLine[];
|
|
43
|
+
subtotalCents: number;
|
|
44
|
+
shippingCents: number;
|
|
45
|
+
shippingLabel: string;
|
|
46
|
+
taxCents: number;
|
|
47
|
+
totalCents: number;
|
|
48
|
+
tracking: PosHardwareTracking | null;
|
|
49
|
+
createdAtMs: number;
|
|
50
|
+
updatedAtMs: number;
|
|
51
|
+
}
|
|
52
|
+
/** Leaves the console for Stripe Checkout, which returns to the card. */
|
|
53
|
+
export declare function openPosHardwareCheckout(url: string): void;
|
|
54
|
+
export declare function posHardwareCatalog(user: User, hostId: string): Promise<PosHardwareCatalog>;
|
|
55
|
+
export declare function posHardwareOrders(user: User, hostId: string): Promise<{
|
|
56
|
+
orders: PosHardwareOrderRow[];
|
|
57
|
+
}>;
|
|
58
|
+
export declare function posHardwareCheckout(user: User, attemptKey: string, body: {
|
|
59
|
+
hostId: string;
|
|
60
|
+
lines: Array<{
|
|
61
|
+
sku: string;
|
|
62
|
+
quantity: number;
|
|
63
|
+
}>;
|
|
64
|
+
shippingMethod: PosHardwareShippingMethod;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
url: string;
|
|
67
|
+
orderId: string;
|
|
68
|
+
}>;
|
|
69
|
+
/** An order as the staff page lists it. */
|
|
70
|
+
export interface StaffHardwareOrderRow extends Omit<PosHardwareOrderRow, 'shippingCents' | 'shippingLabel'> {
|
|
71
|
+
orgId: string;
|
|
72
|
+
hostId: string;
|
|
73
|
+
contactEmail: string | null;
|
|
74
|
+
shipping: {
|
|
75
|
+
method: PosHardwareShippingMethod;
|
|
76
|
+
label: string;
|
|
77
|
+
cents: number;
|
|
78
|
+
name: string | null;
|
|
79
|
+
phone: string | null;
|
|
80
|
+
address: {
|
|
81
|
+
line1: string;
|
|
82
|
+
line2?: string;
|
|
83
|
+
city: string;
|
|
84
|
+
state?: string;
|
|
85
|
+
postalCode: string;
|
|
86
|
+
country: string;
|
|
87
|
+
} | null;
|
|
88
|
+
/** What an account erasure left of the address: where tax is sourced. */
|
|
89
|
+
taxRegion?: {
|
|
90
|
+
country: string;
|
|
91
|
+
state: string | null;
|
|
92
|
+
postalCode: string | null;
|
|
93
|
+
} | null;
|
|
94
|
+
} | null;
|
|
95
|
+
stripeCheckoutSessionId: string | null;
|
|
96
|
+
stripePaymentIntentId: string | null;
|
|
97
|
+
stripeHardwareOrderId: string | null;
|
|
98
|
+
livemode: boolean;
|
|
99
|
+
refundPending: boolean;
|
|
100
|
+
}
|
|
101
|
+
export declare function staffHardwareOrders(user: User, status: PosHardwareOrderStatus | '', after?: string | null): Promise<{
|
|
102
|
+
orders: StaffHardwareOrderRow[];
|
|
103
|
+
next: string | null;
|
|
104
|
+
pageSize: number;
|
|
105
|
+
canWrite: boolean;
|
|
106
|
+
}>;
|
|
107
|
+
export declare function staffHardwareOrderAction(user: User, body: {
|
|
108
|
+
action: 'update' | 'cancel' | 'refund';
|
|
109
|
+
orgId: string;
|
|
110
|
+
orderId: string;
|
|
111
|
+
stripeHardwareOrderId?: string | null;
|
|
112
|
+
tracking?: {
|
|
113
|
+
carrier: string;
|
|
114
|
+
number: string;
|
|
115
|
+
url?: string;
|
|
116
|
+
} | null;
|
|
117
|
+
status?: PosHardwareOrderStatus;
|
|
118
|
+
}): Promise<{
|
|
119
|
+
ok: true;
|
|
120
|
+
order: StaffHardwareOrderRow;
|
|
121
|
+
}>;
|
|
122
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
18
|
+
export class PosHardwareRequestError extends Error {
|
|
19
|
+
constructor(message, status){
|
|
20
|
+
super(message), this.status = status;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function send(user, url, init) {
|
|
24
|
+
var _init_body;
|
|
25
|
+
const response = await authorizedFetch(user, url, _extends({
|
|
26
|
+
method: init.method,
|
|
27
|
+
headers: _extends({}, init.method === 'POST' ? {
|
|
28
|
+
'Content-Type': 'application/json'
|
|
29
|
+
} : {}, init.attemptKey ? {
|
|
30
|
+
'Idempotency-Key': init.attemptKey
|
|
31
|
+
} : {})
|
|
32
|
+
}, init.method === 'POST' ? {
|
|
33
|
+
body: JSON.stringify((_init_body = init.body) != null ? _init_body : {})
|
|
34
|
+
} : {}));
|
|
35
|
+
const payload = await response.json().catch(()=>({}));
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
var _ref;
|
|
38
|
+
throw new PosHardwareRequestError(String((_ref = payload == null ? void 0 : payload.error) != null ? _ref : 'Something went wrong'), response.status);
|
|
39
|
+
}
|
|
40
|
+
return payload;
|
|
41
|
+
}
|
|
42
|
+
const SHOP = '/api/commerce/pos-hardware';
|
|
43
|
+
/** Leaves the console for Stripe Checkout, which returns to the card. */ export function openPosHardwareCheckout(url) {
|
|
44
|
+
window.location.assign(url);
|
|
45
|
+
}
|
|
46
|
+
export function posHardwareCatalog(user, hostId) {
|
|
47
|
+
return send(user, SHOP, {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
body: {
|
|
50
|
+
action: 'catalog',
|
|
51
|
+
hostId
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function posHardwareOrders(user, hostId) {
|
|
56
|
+
return send(user, SHOP, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
body: {
|
|
59
|
+
action: 'orders',
|
|
60
|
+
hostId
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function posHardwareCheckout(user, attemptKey, body) {
|
|
65
|
+
return send(user, SHOP, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
body: _extends({}, body, {
|
|
68
|
+
action: 'checkout'
|
|
69
|
+
}),
|
|
70
|
+
attemptKey
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const STAFF = '/api/commerce/admin/hardware-orders';
|
|
74
|
+
export function staffHardwareOrders(user, status, after = null) {
|
|
75
|
+
const params = new URLSearchParams();
|
|
76
|
+
if (status) params.set('status', status);
|
|
77
|
+
if (after) params.set('after', after);
|
|
78
|
+
const search = params.toString();
|
|
79
|
+
return send(user, search ? `${STAFF}?${search}` : STAFF, {
|
|
80
|
+
method: 'GET'
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export function staffHardwareOrderAction(user, body) {
|
|
84
|
+
return send(user, STAFF, {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
body
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=pos-hardware-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos/pos-hardware-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 { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport type {\n PosHardwareLine,\n PosHardwareOffer,\n PosHardwareOrderStatus,\n PosHardwareShippingMethod,\n PosHardwareTracking,\n} from '../../../model/pos-hardware'\n\n/*\n * The POS hardware shop's client half (AGL-4038): the Hardware card's calls\n * and the staff page's, so neither component builds a request by hand.\n */\n\ntype User = Parameters<typeof authorizedFetch>[0]\n\nexport class PosHardwareRequestError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message)\n }\n}\n\nasync function send<T>(\n user: User,\n url: string,\n init: { method: 'GET' | 'POST'; body?: unknown; attemptKey?: string },\n): Promise<T> {\n const response = await authorizedFetch(user, url, {\n method: init.method,\n headers: {\n ...(init.method === 'POST' ? { 'Content-Type': 'application/json' } : {}),\n ...(init.attemptKey ? { 'Idempotency-Key': init.attemptKey } : {}),\n },\n ...(init.method === 'POST' ? { body: JSON.stringify(init.body ?? {}) } : {}),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n throw new PosHardwareRequestError(String(payload?.error ?? 'Something went wrong'), response.status)\n }\n return payload as T\n}\n\nexport type PosHardwareCatalog =\n | { available: false }\n | {\n available: true\n offers: PosHardwareOffer[]\n shipping: Array<{ method: PosHardwareShippingMethod; label: string; cents: number }>\n automaticTax: boolean\n shipCountries: string[]\n }\n\n/** An order as the Hardware card lists it. */\nexport interface PosHardwareOrderRow {\n id: string\n number: string\n status: PosHardwareOrderStatus\n lines: PosHardwareLine[]\n subtotalCents: number\n shippingCents: number\n shippingLabel: string\n taxCents: number\n totalCents: number\n tracking: PosHardwareTracking | null\n createdAtMs: number\n updatedAtMs: number\n}\n\nconst SHOP = '/api/commerce/pos-hardware'\n\n/** Leaves the console for Stripe Checkout, which returns to the card. */\nexport function openPosHardwareCheckout(url: string): void {\n window.location.assign(url)\n}\n\nexport function posHardwareCatalog(user: User, hostId: string) {\n return send<PosHardwareCatalog>(user, SHOP, { method: 'POST', body: { action: 'catalog', hostId } })\n}\n\nexport function posHardwareOrders(user: User, hostId: string) {\n return send<{ orders: PosHardwareOrderRow[] }>(user, SHOP, {\n method: 'POST',\n body: { action: 'orders', hostId },\n })\n}\n\nexport function posHardwareCheckout(\n user: User,\n attemptKey: string,\n body: {\n hostId: string\n lines: Array<{ sku: string; quantity: number }>\n shippingMethod: PosHardwareShippingMethod\n },\n) {\n return send<{ url: string; orderId: string }>(user, SHOP, {\n method: 'POST',\n body: { ...body, action: 'checkout' },\n attemptKey,\n })\n}\n\n/** An order as the staff page lists it. */\nexport interface StaffHardwareOrderRow extends Omit<PosHardwareOrderRow, 'shippingCents' | 'shippingLabel'> {\n orgId: string\n hostId: string\n contactEmail: string | null\n shipping: {\n method: PosHardwareShippingMethod\n label: string\n cents: number\n name: string | null\n phone: string | null\n address: {\n line1: string\n line2?: string\n city: string\n state?: string\n postalCode: string\n country: string\n } | null\n /** What an account erasure left of the address: where tax is sourced. */\n taxRegion?: { country: string; state: string | null; postalCode: string | null } | null\n } | null\n stripeCheckoutSessionId: string | null\n stripePaymentIntentId: string | null\n stripeHardwareOrderId: string | null\n livemode: boolean\n refundPending: boolean\n}\n\nconst STAFF = '/api/commerce/admin/hardware-orders'\n\nexport function staffHardwareOrders(user: User, status: PosHardwareOrderStatus | '', after: string | null = null) {\n const params = new URLSearchParams()\n if (status) params.set('status', status)\n if (after) params.set('after', after)\n const search = params.toString()\n return send<{ orders: StaffHardwareOrderRow[]; next: string | null; pageSize: number; canWrite: boolean }>(\n user,\n search ? `${STAFF}?${search}` : STAFF,\n { method: 'GET' },\n )\n}\n\nexport function staffHardwareOrderAction(\n user: User,\n body: {\n action: 'update' | 'cancel' | 'refund'\n orgId: string\n orderId: string\n stripeHardwareOrderId?: string | null\n tracking?: { carrier: string; number: string; url?: string } | null\n status?: PosHardwareOrderStatus\n },\n) {\n return send<{ ok: true; order: StaffHardwareOrderRow }>(user, STAFF, { method: 'POST', body })\n}\n"],"names":["authorizedFetch","PosHardwareRequestError","Error","message","status","send","user","url","init","response","method","headers","attemptKey","body","JSON","stringify","payload","json","catch","ok","String","error","SHOP","openPosHardwareCheckout","window","location","assign","posHardwareCatalog","hostId","action","posHardwareOrders","posHardwareCheckout","STAFF","staffHardwareOrders","after","params","URLSearchParams","set","search","toString","staffHardwareOrderAction"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,eAAe,QAAQ,2CAA0C;AAgB1E,OAAO,MAAMC,gCAAgCC;IAC3C,YACEC,OAAe,EACf,AAASC,MAAc,CACvB;QACA,KAAK,CAACD,eAFGC,SAAAA;IAGX;AACF;AAEA,eAAeC,KACbC,IAAU,EACVC,GAAW,EACXC,IAAqE;QAQfA;IANtD,MAAMC,WAAW,MAAMT,gBAAgBM,MAAMC,KAAK;QAChDG,QAAQF,KAAKE,MAAM;QACnBC,SAAS,aACHH,KAAKE,MAAM,KAAK,SAAS;YAAE,gBAAgB;QAAmB,IAAI,CAAC,GACnEF,KAAKI,UAAU,GAAG;YAAE,mBAAmBJ,KAAKI,UAAU;QAAC,IAAI,CAAC;OAE9DJ,KAAKE,MAAM,KAAK,SAAS;QAAEG,MAAMC,KAAKC,SAAS,EAACP,aAAAA,KAAKK,IAAI,YAATL,aAAa,CAAC;IAAG,IAAI,CAAC;IAE5E,MAAMQ,UAAU,MAAMP,SAASQ,IAAI,GAAGC,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;IACpD,IAAI,CAACT,SAASU,EAAE,EAAE;;QAChB,MAAM,IAAIlB,wBAAwBmB,eAAOJ,2BAAAA,QAASK,KAAK,mBAAI,yBAAyBZ,SAASL,MAAM;IACrG;IACA,OAAOY;AACT;AA4BA,MAAMM,OAAO;AAEb,uEAAuE,GACvE,OAAO,SAASC,wBAAwBhB,GAAW;IACjDiB,OAAOC,QAAQ,CAACC,MAAM,CAACnB;AACzB;AAEA,OAAO,SAASoB,mBAAmBrB,IAAU,EAAEsB,MAAc;IAC3D,OAAOvB,KAAyBC,MAAMgB,MAAM;QAAEZ,QAAQ;QAAQG,MAAM;YAAEgB,QAAQ;YAAWD;QAAO;IAAE;AACpG;AAEA,OAAO,SAASE,kBAAkBxB,IAAU,EAAEsB,MAAc;IAC1D,OAAOvB,KAAwCC,MAAMgB,MAAM;QACzDZ,QAAQ;QACRG,MAAM;YAAEgB,QAAQ;YAAUD;QAAO;IACnC;AACF;AAEA,OAAO,SAASG,oBACdzB,IAAU,EACVM,UAAkB,EAClBC,IAIC;IAED,OAAOR,KAAuCC,MAAMgB,MAAM;QACxDZ,QAAQ;QACRG,MAAM,aAAKA;YAAMgB,QAAQ;;QACzBjB;IACF;AACF;AA+BA,MAAMoB,QAAQ;AAEd,OAAO,SAASC,oBAAoB3B,IAAU,EAAEF,MAAmC,EAAE8B,QAAuB,IAAI;IAC9G,MAAMC,SAAS,IAAIC;IACnB,IAAIhC,QAAQ+B,OAAOE,GAAG,CAAC,UAAUjC;IACjC,IAAI8B,OAAOC,OAAOE,GAAG,CAAC,SAASH;IAC/B,MAAMI,SAASH,OAAOI,QAAQ;IAC9B,OAAOlC,KACLC,MACAgC,SAAS,GAAGN,MAAM,CAAC,EAAEM,QAAQ,GAAGN,OAChC;QAAEtB,QAAQ;IAAM;AAEpB;AAEA,OAAO,SAAS8B,yBACdlC,IAAU,EACVO,IAOC;IAED,OAAOR,KAAiDC,MAAM0B,OAAO;QAAEtB,QAAQ;QAAQG;IAAK;AAC9F"}
|