@aglyn/plugins-commerce 1.0.0-beta.278 → 1.0.0-beta.283
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
|
@@ -28,7 +28,8 @@ export interface PosOperationsBarProps {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* The register's operations strip (AGL-3609): who is ringing (and a PIN
|
|
31
|
-
* switch to someone else), the shift and drawer,
|
|
31
|
+
* switch to someone else), the shift and drawer, check-in at the window
|
|
32
|
+
* (AGL-4043), returns, and the lock. Sits
|
|
32
33
|
* above the basket; every control is a tablet-sized button.
|
|
33
34
|
*/
|
|
34
35
|
export declare function PosOperationsBar(props: PosOperationsBarProps): import("react").JSX.Element;
|
|
@@ -18,17 +18,20 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
18
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
19
|
import { Box, Button, Chip, Stack, Typography } from "@mui/material";
|
|
20
20
|
import { useState } from "react";
|
|
21
|
+
import { PosCheckInDialog } from "./pos-check-in-dialog.component.js";
|
|
21
22
|
import { PosPinPad } from "./pos-pin-pad.component.js";
|
|
22
23
|
import { PosReturnDialog } from "./pos-return-dialog.component.js";
|
|
23
24
|
import { PosShiftPanel } from "./pos-shift-panel.component.js";
|
|
24
25
|
/**
|
|
25
26
|
* The register's operations strip (AGL-3609): who is ringing (and a PIN
|
|
26
|
-
* switch to someone else), the shift and drawer,
|
|
27
|
+
* switch to someone else), the shift and drawer, check-in at the window
|
|
28
|
+
* (AGL-4043), returns, and the lock. Sits
|
|
27
29
|
* above the basket; every control is a tablet-sized button.
|
|
28
30
|
*/ export function PosOperationsBar(props) {
|
|
29
31
|
const { hostId, registerId, cashier } = props;
|
|
30
32
|
const [switching, setSwitching] = useState(false);
|
|
31
33
|
const [returning, setReturning] = useState(false);
|
|
34
|
+
const [checkingIn, setCheckingIn] = useState(false);
|
|
32
35
|
return /*#__PURE__*/ _jsxs(Stack, {
|
|
33
36
|
spacing: 1,
|
|
34
37
|
children: [
|
|
@@ -65,6 +68,12 @@ import { PosShiftPanel } from "./pos-shift-panel.component.js";
|
|
|
65
68
|
flex: 1
|
|
66
69
|
}
|
|
67
70
|
}),
|
|
71
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
72
|
+
size: "small",
|
|
73
|
+
variant: "outlined",
|
|
74
|
+
onClick: ()=>setCheckingIn(true),
|
|
75
|
+
children: 'Check in'
|
|
76
|
+
}),
|
|
68
77
|
/*#__PURE__*/ _jsx(Button, {
|
|
69
78
|
size: "small",
|
|
70
79
|
variant: "outlined",
|
|
@@ -104,6 +113,16 @@ import { PosShiftPanel } from "./pos-shift-panel.component.js";
|
|
|
104
113
|
onClose: cashier.unlock,
|
|
105
114
|
onVerified: cashier.switchTo
|
|
106
115
|
}),
|
|
116
|
+
/*#__PURE__*/ _jsx(PosCheckInDialog, _extends({
|
|
117
|
+
open: checkingIn,
|
|
118
|
+
hostId: hostId
|
|
119
|
+
}, registerId ? {
|
|
120
|
+
registerId
|
|
121
|
+
} : {}, cashier.assertion ? {
|
|
122
|
+
cashierAssertion: cashier.assertion
|
|
123
|
+
} : {}, {
|
|
124
|
+
onClose: ()=>setCheckingIn(false)
|
|
125
|
+
})),
|
|
107
126
|
/*#__PURE__*/ _jsx(PosReturnDialog, _extends({
|
|
108
127
|
open: returning,
|
|
109
128
|
hostId: hostId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-operations-bar.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\n'use client'\n\nimport { Box, Button, Chip, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\nimport { PosPinPad } from './pos-pin-pad.component'\nimport { PosReturnDialog } from './pos-return-dialog.component'\nimport { PosShiftPanel } from './pos-shift-panel.component'\nimport type { PosCashierState } from './use-pos-cashier'\n\nexport interface PosOperationsBarProps {\n hostId: string\n registerId: string\n registerName?: string\n cashier: PosCashierState\n /** Ring the exchange after a return: a new sale for the same customer. */\n onExchange?: (customer: { email: string | null; name: string | null }) => void\n}\n\n/**\n * The register's operations strip (AGL-3609): who is ringing (and a PIN\n * switch to someone else), the shift and drawer, returns, and the lock. Sits\n * above the basket; every control is a tablet-sized button.\n */\nexport function PosOperationsBar(props: PosOperationsBarProps) {\n const { hostId, registerId, cashier } = props\n const [switching, setSwitching] = useState(false)\n const [returning, setReturning] = useState(false)\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={cashier.cashier ? `Cashier: ${cashier.cashier.name}` : 'Cashier: you'}\n {...(cashier.cashier ? { onDelete: cashier.signOutCashier } : {})}\n />\n <Button size=\"small\" onClick={() => setSwitching(true)} disabled={!registerId}>\n {'Switch cashier'}\n </Button>\n <Button size=\"small\" onClick={cashier.lock} disabled={!registerId}>\n {'Lock'}\n </Button>\n <Box sx={{ flex: 1 }} />\n <Button size=\"small\" variant=\"outlined\" onClick={() => setReturning(true)} disabled={!registerId}>\n {'Return'}\n </Button>\n </Stack>\n {registerId ? (\n <PosShiftPanel\n hostId={hostId}\n registerId={registerId}\n {...(props.registerName ? { registerName: props.registerName } : {})}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n />\n ) : null}\n <PosPinPad\n open={switching}\n hostId={hostId}\n registerId={registerId}\n purpose=\"cashier\"\n onClose={() => setSwitching(false)}\n onVerified={(assertion) => {\n cashier.switchTo(assertion)\n setSwitching(false)\n }}\n />\n <PosPinPad\n open={cashier.locked}\n hostId={hostId}\n registerId={registerId}\n purpose=\"cashier\"\n title=\"Register locked\"\n prompt=\"Enter your PIN to use the register.\"\n dismissible={false}\n onClose={cashier.unlock}\n onVerified={cashier.switchTo}\n />\n <PosReturnDialog\n open={returning}\n hostId={hostId}\n registerId={registerId}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n onClose={() => setReturning(false)}\n {...(props.onExchange ? { onExchange: props.onExchange } : {})}\n />\n {cashier.locked ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Locked'}\n </Typography>\n ) : null}\n </Stack>\n )\n}\n\nPosOperationsBar.displayName = 'PosOperationsBar'\n\nexport default PosOperationsBar\n"],"names":["Box","Button","Chip","Stack","Typography","useState","PosPinPad","PosReturnDialog","PosShiftPanel","PosOperationsBar","props","hostId","registerId","cashier","switching","setSwitching","returning","setReturning","spacing","direction","useFlexGap","sx","alignItems","flexWrap","size","variant","label","name","onDelete","signOutCashier","onClick","disabled","lock","flex","registerName","assertion","cashierAssertion","open","purpose","onClose","onVerified","switchTo","locked","title","prompt","dismissible","unlock","onExchange","color","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;AAEA,SAASA,GAAG,EAAEC,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AACpE,SAASC,QAAQ,QAAQ,QAAO;AAChC,SAASC,SAAS,QAAQ,6BAAyB;AACnD,SAASC,eAAe,QAAQ,mCAA+B;AAC/D,SAASC,aAAa,QAAQ,iCAA6B;AAY3D
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-operations-bar.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\n'use client'\n\nimport { Box, Button, Chip, Stack, Typography } from '@mui/material'\nimport { useState } from 'react'\nimport { PosCheckInDialog } from './pos-check-in-dialog.component'\nimport { PosPinPad } from './pos-pin-pad.component'\nimport { PosReturnDialog } from './pos-return-dialog.component'\nimport { PosShiftPanel } from './pos-shift-panel.component'\nimport type { PosCashierState } from './use-pos-cashier'\n\nexport interface PosOperationsBarProps {\n hostId: string\n registerId: string\n registerName?: string\n cashier: PosCashierState\n /** Ring the exchange after a return: a new sale for the same customer. */\n onExchange?: (customer: { email: string | null; name: string | null }) => void\n}\n\n/**\n * The register's operations strip (AGL-3609): who is ringing (and a PIN\n * switch to someone else), the shift and drawer, check-in at the window\n * (AGL-4043), returns, and the lock. Sits\n * above the basket; every control is a tablet-sized button.\n */\nexport function PosOperationsBar(props: PosOperationsBarProps) {\n const { hostId, registerId, cashier } = props\n const [switching, setSwitching] = useState(false)\n const [returning, setReturning] = useState(false)\n const [checkingIn, setCheckingIn] = useState(false)\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ alignItems: 'center', flexWrap: 'wrap' }}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={cashier.cashier ? `Cashier: ${cashier.cashier.name}` : 'Cashier: you'}\n {...(cashier.cashier ? { onDelete: cashier.signOutCashier } : {})}\n />\n <Button size=\"small\" onClick={() => setSwitching(true)} disabled={!registerId}>\n {'Switch cashier'}\n </Button>\n <Button size=\"small\" onClick={cashier.lock} disabled={!registerId}>\n {'Lock'}\n </Button>\n <Box sx={{ flex: 1 }} />\n <Button size=\"small\" variant=\"outlined\" onClick={() => setCheckingIn(true)}>\n {'Check in'}\n </Button>\n <Button size=\"small\" variant=\"outlined\" onClick={() => setReturning(true)} disabled={!registerId}>\n {'Return'}\n </Button>\n </Stack>\n {registerId ? (\n <PosShiftPanel\n hostId={hostId}\n registerId={registerId}\n {...(props.registerName ? { registerName: props.registerName } : {})}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n />\n ) : null}\n <PosPinPad\n open={switching}\n hostId={hostId}\n registerId={registerId}\n purpose=\"cashier\"\n onClose={() => setSwitching(false)}\n onVerified={(assertion) => {\n cashier.switchTo(assertion)\n setSwitching(false)\n }}\n />\n <PosPinPad\n open={cashier.locked}\n hostId={hostId}\n registerId={registerId}\n purpose=\"cashier\"\n title=\"Register locked\"\n prompt=\"Enter your PIN to use the register.\"\n dismissible={false}\n onClose={cashier.unlock}\n onVerified={cashier.switchTo}\n />\n <PosCheckInDialog\n open={checkingIn}\n hostId={hostId}\n {...(registerId ? { registerId } : {})}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n onClose={() => setCheckingIn(false)}\n />\n <PosReturnDialog\n open={returning}\n hostId={hostId}\n registerId={registerId}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n onClose={() => setReturning(false)}\n {...(props.onExchange ? { onExchange: props.onExchange } : {})}\n />\n {cashier.locked ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Locked'}\n </Typography>\n ) : null}\n </Stack>\n )\n}\n\nPosOperationsBar.displayName = 'PosOperationsBar'\n\nexport default PosOperationsBar\n"],"names":["Box","Button","Chip","Stack","Typography","useState","PosCheckInDialog","PosPinPad","PosReturnDialog","PosShiftPanel","PosOperationsBar","props","hostId","registerId","cashier","switching","setSwitching","returning","setReturning","checkingIn","setCheckingIn","spacing","direction","useFlexGap","sx","alignItems","flexWrap","size","variant","label","name","onDelete","signOutCashier","onClick","disabled","lock","flex","registerName","assertion","cashierAssertion","open","purpose","onClose","onVerified","switchTo","locked","title","prompt","dismissible","unlock","onExchange","color","displayName"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
/** The register's operations routes (AGL-3609). */
|
|
18
|
-
export type PosOpsRoute = 'pos-shift' | 'pos-staff-pin' | 'pos-customer' | 'pos-return';
|
|
18
|
+
export type PosOpsRoute = 'pos-shift' | 'pos-staff-pin' | 'pos-customer' | 'pos-return' | 'pos-check-in';
|
|
19
19
|
export interface PosOpsAnswer<T = Record<string, any>> {
|
|
20
20
|
ok: boolean;
|
|
21
21
|
status: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-ops-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'\n\n/** The register's operations routes (AGL-3609). */\nexport type PosOpsRoute = 'pos-shift' | 'pos-staff-pin' | 'pos-customer' | 'pos-return'\n\nexport interface PosOpsAnswer<T = Record<string, any>> {\n ok: boolean\n status: number\n body: T & { error?: string }\n}\n\n/**\n * One call to a register route, answered as data — a refusal is a status and\n * a sentence for the cashier, never a throw the register has to catch. A\n * network failure answers status 0.\n */\nexport async function callPosOps<T = Record<string, any>>(\n user: unknown,\n route: PosOpsRoute,\n body: Record<string, unknown>,\n options: { idempotencyKey?: string } = {},\n): Promise<PosOpsAnswer<T>> {\n try {\n const response = await authorizedFetch(user as any, `/api/commerce/${route}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(options.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : {}),\n },\n body: JSON.stringify(body),\n })\n const parsed = (await response.json().catch(() => ({}))) as T & { error?: string }\n return { ok: response.ok, status: response.status, body: parsed }\n } catch {\n return {\n ok: false,\n status: 0,\n body: { error: 'The register is offline. Check the connection and try again.' } as T & {\n error?: string\n },\n }\n }\n}\n\n/** A fresh attempt id for one tap that moves money or cash. */\nexport function newPosAttemptKey(): string {\n const random =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`\n return random.replace(/[^A-Za-z0-9_-]/g, '')\n}\n\n/** Dollars typed at the register → whole cents, or `null` for not-an-amount. */\nexport function parsePosDollars(value: string): number | null {\n const trimmed = String(value ?? '').replace(/[$,\\s]/g, '')\n if (!trimmed) return null\n if (!/^\\d+(\\.\\d{0,2})?$/.test(trimmed)) return null\n return Math.round(Number(trimmed) * 100)\n}\n"],"names":["authorizedFetch","callPosOps","user","route","body","options","response","method","headers","idempotencyKey","JSON","stringify","parsed","json","catch","ok","status","error","newPosAttemptKey","random","crypto","randomUUID","Date","now","Math","toString","slice","replace","parsePosDollars","value","trimmed","String","test","round","Number"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,eAAe,QAAQ,2CAA0C;AAW1E;;;;CAIC,GACD,OAAO,eAAeC,WACpBC,IAAa,EACbC,KAAkB,EAClBC,IAA6B,EAC7BC,UAAuC,CAAC,CAAC;IAEzC,IAAI;QACF,MAAMC,WAAW,MAAMN,gBAAgBE,MAAa,CAAC,cAAc,EAAEC,OAAO,EAAE;YAC5EI,QAAQ;YACRC,SAAS;gBACP,gBAAgB;eACZH,QAAQI,cAAc,GAAG;gBAAE,mBAAmBJ,QAAQI,cAAc;YAAC,IAAI,CAAC;YAEhFL,MAAMM,KAAKC,SAAS,CAACP;QACvB;QACA,MAAMQ,SAAU,MAAMN,SAASO,IAAI,GAAGC,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;QACpD,OAAO;YAAEC,IAAIT,SAASS,EAAE;YAAEC,QAAQV,SAASU,MAAM;YAAEZ,MAAMQ;QAAO;IAClE,EAAE,eAAM;QACN,OAAO;YACLG,IAAI;YACJC,QAAQ;YACRZ,MAAM;gBAAEa,OAAO;YAA+D;QAGhF;IACF;AACF;AAEA,6DAA6D,GAC7D,OAAO,SAASC;IACd,MAAMC,SACJ,OAAOC,WAAW,eAAe,gBAAgBA,SAC7CA,OAAOC,UAAU,KACjB,GAAGC,KAAKC,GAAG,GAAG,CAAC,EAAEC,KAAKL,MAAM,GAAGM,QAAQ,CAAC,IAAIC,KAAK,CAAC,IAAI;IAC5D,OAAOP,OAAOQ,OAAO,CAAC,mBAAmB;AAC3C;AAEA,8EAA8E,GAC9E,OAAO,SAASC,gBAAgBC,KAAa;IAC3C,MAAMC,UAAUC,OAAOF,gBAAAA,QAAS,IAAIF,OAAO,CAAC,WAAW;IACvD,IAAI,CAACG,SAAS,OAAO;IACrB,IAAI,CAAC,oBAAoBE,IAAI,CAACF,UAAU,OAAO;IAC/C,OAAON,KAAKS,KAAK,CAACC,OAAOJ,WAAW;AACtC"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-ops-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'\n\n/** The register's operations routes (AGL-3609). */\nexport type PosOpsRoute = 'pos-shift' | 'pos-staff-pin' | 'pos-customer' | 'pos-return' | 'pos-check-in'\n\nexport interface PosOpsAnswer<T = Record<string, any>> {\n ok: boolean\n status: number\n body: T & { error?: string }\n}\n\n/**\n * One call to a register route, answered as data — a refusal is a status and\n * a sentence for the cashier, never a throw the register has to catch. A\n * network failure answers status 0.\n */\nexport async function callPosOps<T = Record<string, any>>(\n user: unknown,\n route: PosOpsRoute,\n body: Record<string, unknown>,\n options: { idempotencyKey?: string } = {},\n): Promise<PosOpsAnswer<T>> {\n try {\n const response = await authorizedFetch(user as any, `/api/commerce/${route}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(options.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : {}),\n },\n body: JSON.stringify(body),\n })\n const parsed = (await response.json().catch(() => ({}))) as T & { error?: string }\n return { ok: response.ok, status: response.status, body: parsed }\n } catch {\n return {\n ok: false,\n status: 0,\n body: { error: 'The register is offline. Check the connection and try again.' } as T & {\n error?: string\n },\n }\n }\n}\n\n/** A fresh attempt id for one tap that moves money or cash. */\nexport function newPosAttemptKey(): string {\n const random =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`\n return random.replace(/[^A-Za-z0-9_-]/g, '')\n}\n\n/** Dollars typed at the register → whole cents, or `null` for not-an-amount. */\nexport function parsePosDollars(value: string): number | null {\n const trimmed = String(value ?? '').replace(/[$,\\s]/g, '')\n if (!trimmed) return null\n if (!/^\\d+(\\.\\d{0,2})?$/.test(trimmed)) return null\n return Math.round(Number(trimmed) * 100)\n}\n"],"names":["authorizedFetch","callPosOps","user","route","body","options","response","method","headers","idempotencyKey","JSON","stringify","parsed","json","catch","ok","status","error","newPosAttemptKey","random","crypto","randomUUID","Date","now","Math","toString","slice","replace","parsePosDollars","value","trimmed","String","test","round","Number"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,eAAe,QAAQ,2CAA0C;AAW1E;;;;CAIC,GACD,OAAO,eAAeC,WACpBC,IAAa,EACbC,KAAkB,EAClBC,IAA6B,EAC7BC,UAAuC,CAAC,CAAC;IAEzC,IAAI;QACF,MAAMC,WAAW,MAAMN,gBAAgBE,MAAa,CAAC,cAAc,EAAEC,OAAO,EAAE;YAC5EI,QAAQ;YACRC,SAAS;gBACP,gBAAgB;eACZH,QAAQI,cAAc,GAAG;gBAAE,mBAAmBJ,QAAQI,cAAc;YAAC,IAAI,CAAC;YAEhFL,MAAMM,KAAKC,SAAS,CAACP;QACvB;QACA,MAAMQ,SAAU,MAAMN,SAASO,IAAI,GAAGC,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;QACpD,OAAO;YAAEC,IAAIT,SAASS,EAAE;YAAEC,QAAQV,SAASU,MAAM;YAAEZ,MAAMQ;QAAO;IAClE,EAAE,eAAM;QACN,OAAO;YACLG,IAAI;YACJC,QAAQ;YACRZ,MAAM;gBAAEa,OAAO;YAA+D;QAGhF;IACF;AACF;AAEA,6DAA6D,GAC7D,OAAO,SAASC;IACd,MAAMC,SACJ,OAAOC,WAAW,eAAe,gBAAgBA,SAC7CA,OAAOC,UAAU,KACjB,GAAGC,KAAKC,GAAG,GAAG,CAAC,EAAEC,KAAKL,MAAM,GAAGM,QAAQ,CAAC,IAAIC,KAAK,CAAC,IAAI;IAC5D,OAAOP,OAAOQ,OAAO,CAAC,mBAAmB;AAC3C;AAEA,8EAA8E,GAC9E,OAAO,SAASC,gBAAgBC,KAAa;IAC3C,MAAMC,UAAUC,OAAOF,gBAAAA,QAAS,IAAIF,OAAO,CAAC,WAAW;IACvD,IAAI,CAACG,SAAS,OAAO;IACrB,IAAI,CAAC,oBAAoBE,IAAI,CAACF,UAAU,OAAO;IAC/C,OAAON,KAAKS,KAAK,CAACC,OAAOJ,WAAW;AACtC"}
|
|
@@ -848,11 +848,14 @@ export function PosConsolePage({ hostId, basePath }) {
|
|
|
848
848
|
},
|
|
849
849
|
discountPct: discountPct,
|
|
850
850
|
onDiscountPct: setDiscountPct,
|
|
851
|
-
customer: sale ? null : /*#__PURE__*/ _jsx(PosCustomerLookup, {
|
|
851
|
+
customer: sale ? null : /*#__PURE__*/ _jsx(PosCustomerLookup, _extends({
|
|
852
852
|
hostId: hostId,
|
|
853
853
|
value: customer,
|
|
854
|
-
onChange: setCustomer
|
|
855
|
-
|
|
854
|
+
onChange: setCustomer,
|
|
855
|
+
registerId: registerId
|
|
856
|
+
}, cashier.assertion ? {
|
|
857
|
+
cashierAssertion: cashier.assertion
|
|
858
|
+
} : {})),
|
|
856
859
|
locked: Boolean(sale)
|
|
857
860
|
}),
|
|
858
861
|
sale && user ? sale.status === 'paid' ? /*#__PURE__*/ _jsx(PosReceiptPanel, _extends({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-page.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport * as CommerceModel from '../../model'\nimport {\n PRODUCT_LIST_BASE,\n PRODUCT_LIST_QUERY,\n} from '../../constants/product-list-query'\nimport { NextPageTitle } from '@aglyn/shared-ui-next/contexts/next-page-title-provider'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport type { ListFilterRequest } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport { planListQuery } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { useViewportFill } from '@aglyn/shared-ui-jsx/hooks/use-viewport-fill'\nimport { nameSearchNormalizers } from '@aglyn/aglyn/app-utils/name-search'\nimport {\n Badge,\n Box,\n Button,\n Drawer,\n MenuItem,\n Stack,\n TextField,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport {\n collection,\n getDocs,\n limit,\n query,\n where,\n} from 'firebase/firestore'\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { listQueryConstraints } from '@aglyn/tenant-feature-instance/hooks/use-list-query'\nimport { useOrgPlan } from '@aglyn/tenant-feature-instance'\nimport {\n newAttemptKey,\n openPosSale,\n posRegisterContext,\n posTender,\n PosRequestError,\n usd,\n type PosRegisterContext,\n type PosSaleSummary,\n} from './pos/pos-api'\nimport { PosCartPanel, type RegisterLine } from './pos/pos-cart-panel.component'\nimport { ScanAdornment } from '../../barcode/scan-button.component'\nimport { useScannerWedge } from '../../barcode/scanner-wedge'\nimport {\n PosCustomerLookup,\n PosLastReceipt,\n PosOperationsBar,\n usePosCashier,\n usePosOpsSettings,\n type PosSelectedCustomer,\n} from './pos-ops/register-ops'\nimport { POS_QUICK_KEYS, POS_TOUCH_PX, PosProductGrid } from './pos/pos-product-grid.component'\nimport { PosItemDialog, posItemNeedsChoice, type PosItemChoice } from './pos/pos-item-dialog.component'\nimport { PosReceiptPanel } from './pos/pos-receipt-panel.component'\nimport { PosTenderPanel } from './pos/pos-tender-panel.component'\nimport { PosKioskQueue } from './pos/pos-kiosk-queue.component'\nimport { posDisplayTipCents, usePosDisplay } from './pos/use-pos-display'\nimport { posRegistersSettingsHref, usePosPairing } from './pos/pos-pairing.component'\nimport {\n type ConsoleWidgetSlotRenderer,\n useConsoleWidgetSlot,\n} from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport { POS_ORDERS_ZONE } from './pos-zones'\nimport { PosOfflineBanner, PosOfflineCheckout, usePosOffline } from './pos-offline/register-offline'\n\n/** The till sells active products only; every read of the catalog asks it. */\nconst SELLABLE: ListFilterRequest = { field: 'status', op: 'equals', value: 'active' }\n\n/**\n * How many products the till's grid shows. The grid is a picker, not the\n * catalog: typing narrows it on the query, so a name reaches every product.\n */\nconst POS_GRID_CEILING = 500\n\n/**\n * The products hub's query (AGL-3321), narrowed to what the till may sell:\n * live products (`deletedAt == null`, the list's scope), `status == active`,\n * and any typed word as the search on `nameTokens` — or, for a scan, the\n * whole scanned code as a SKU or barcode clause. Every shape is one the hub's\n * composites already serve.\n */\nexport function posProductPlan(options: {\n search?: string\n code?: { field: 'barcodes' | 'skus'; value: string }\n /** A category chip (AGL-3607): served by the storefront's own composite. */\n categoryId?: string\n /** The Quick keys chip (AGL-3607): products marked `posQuickKey`. */\n quickKeys?: boolean\n}) {\n const typed = options.search?.trim()\n const plan = planListQuery(\n POS_GRID_QUERY,\n {\n base: PRODUCT_LIST_BASE,\n clauses: [\n SELLABLE,\n ...(options.code\n ? [{ field: options.code.field, op: 'contains', value: options.code.value }]\n : []),\n ...(options.categoryId\n ? [{ field: 'categoryIds', op: 'contains', value: options.categoryId }]\n : []),\n ],\n // A chip and a typed word are both array clauses, and Firestore takes\n // one: with a chip on, the word narrows by name prefix instead.\n search: typed && !options.categoryId ? [typed] : [],\n },\n nameSearchNormalizers,\n )\n // The Quick keys chip (AGL-3607) is a boolean equality the list planner\n // does not model, added beside the scope and status it composes with —\n // `deletedAt ==, status ==, posQuickKey ==, nameLower ASC` is declared in\n // the index file. A typed word searches the whole catalog instead: a\n // cashier who types is looking past the quick keys.\n if (options.quickKeys && !typed && !options.code) {\n return {\n ...plan,\n filters: [...plan.filters, { path: 'posQuickKey', op: '==', value: true }],\n } as typeof plan\n }\n return plan\n}\n\n/**\n * The grid's query: the products hub's, plus the category a chip picks\n * (AGL-3607). `categoryIds CONTAINS, nameLower ASC` is a composite the\n * storefront catalog already declares.\n */\nexport const POS_GRID_QUERY = {\n ...PRODUCT_LIST_QUERY,\n fields: [\n ...PRODUCT_LIST_QUERY.fields,\n {\n column: 'categoryIds',\n kind: 'exact' as const,\n path: 'categoryIds',\n tokensPath: 'categoryIds',\n operators: ['contains'],\n },\n ],\n} as typeof PRODUCT_LIST_QUERY\n\n/**\n * POS register (AGL-312, AGL-3607): a tablet-first sale surface — the\n * product grid with search, scan and category chips, the basket, and a\n * tender panel that takes one or more payments against an open sale (cash,\n * card reader, a native Tap to Pay bridge, a typed card, the QR link, gift\n * cards and room charges) until the balance is zero. A paired customer\n * display mirrors the basket and takes the tip and the receipt (AGL-3608).\n *\n * On a wide screen (900px and up) the grid and the register sit side by\n * side; below that the register is a bottom sheet behind a sticky total bar.\n */\n/*\n * `managePos` is NOT read here. The nav item in `plugin.ts` declares it and\n * the shell refuses the route before this component is constructed, so a\n * reader without the key never reaches this file and there is no unpermitted\n * state for it to render — the same arrangement the entitlement gate has.\n *\n * Re-adding a check off the `permissions` prop would be a second answer to a\n * settled question, and a laxer one: a prop absent because the map has not\n * landed reads as permitted here, while the shell holds the route on that\n * same condition rather than guessing. The server routes remain the\n * enforcement point for every sale and every payment.\n */\n/** Where a register device remembers the category chip it was left on. */\nconst POS_CATEGORY_KEY = 'aglyn.pos.category'\n\n/** The basket line an item-sheet choice makes: label and estimate from the product. */\nexport function registerLineFor(\n product: any,\n choice: PosItemChoice,\n): RegisterLine {\n const { variant, modifiers, quantity } = choice\n const resolved = CommerceModel.resolveLineModifiers(product, modifiers)\n const picked = resolved.ok ? resolved.modifiers : []\n const label = CommerceModel.lineLabelWithModifiers(\n Object.keys(variant.options ?? {}).length\n ? Object.values(variant.options ?? {}).join(' / ')\n : undefined,\n picked,\n )\n return {\n productId: product.$id,\n ...(variant.id !== 'default' ? { variantId: variant.id } : {}),\n name: product.name,\n ...(label ? { variantLabel: label } : {}),\n unitAmountCents:\n Math.round(Number(variant.priceUsd) * 100) + (resolved.ok ? resolved.extraCents : 0),\n quantity,\n ...(modifiers.length ? { modifiers } : {}),\n }\n}\n\n/** Same product, variant and choices: the lines that merge into one. */\nfunction lineKey(line: Pick<RegisterLine, 'productId' | 'variantId' | 'modifiers'>): string {\n return `${line.productId}:${line.variantId ?? ''}:${CommerceModel.modifierSelectionKey(line.modifiers)}`\n}\n\n/**\n * The register's zone (AGL-3644), drawn again only when what it is handed\n * changes: the till redraws on every tap, and the shell's renderer is not\n * memoized (the order dialog's reasoning).\n */\nconst PosOrdersZone = memo(function PosOrdersZone(props: {\n renderer: ConsoleWidgetSlotRenderer\n hostId: string\n registerId: string | null\n}) {\n const { renderer: Renderer, hostId, registerId } = props\n return <Renderer slot={POS_ORDERS_ZONE.id} hostId={hostId} orgId={undefined} registerId={registerId} />\n})\n\nexport function PosConsolePage({ hostId, basePath }: ConsolePluginPageProps) {\n const WidgetSlot = useConsoleWidgetSlot()\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const theme = useTheme()\n const wide = useMediaQuery(theme.breakpoints.up('md'))\n\n const [search, setSearch] = useState('')\n // The chip a register opens on is remembered per device: a counter that\n // rings from its quick keys reopens on them.\n const [categoryId, setCategoryIdState] = useState(() => {\n try {\n return window.localStorage.getItem(POS_CATEGORY_KEY) ?? ''\n } catch {\n return ''\n }\n })\n const setCategoryId = useCallback((id: string) => {\n setCategoryIdState(id)\n try {\n window.localStorage.setItem(POS_CATEGORY_KEY, id)\n } catch {\n // Storage blocked: the chip still works for this visit.\n }\n }, [])\n const gridPlan = useMemo(\n () =>\n categoryId === POS_QUICK_KEYS\n ? posProductPlan({ search, quickKeys: true })\n : posProductPlan({ search, categoryId }),\n [search, categoryId],\n )\n const { data: productDocs } = useFirestoreCollection<any>(\n /*\n * The till's grid, narrowed by the QUERY rather than by the rows it\n * happened to fetch (AGL-2501, AGL-2292, AGL-3321): the first five\n * hundred SELLABLE products by name, and a typed name reaches the whole\n * catalog. The scan does not come through here — see `handleSearchEnter`.\n */\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(gridPlan),\n limit(POS_GRID_CEILING),\n ),\n [firestore, hostId, gridPlan],\n { idField: '$id' },\n )\n const { data: categoryDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'productCategories'), limit(30)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: locationDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'locations'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: registerDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'registers'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { org, ready: planReady } = useOrgPlan(hostId)\n const registers = [...(registerDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n // Only registers within the plan cap can transact (AGL-482), and not until\n // the org doc has arrived (AGL-1064). Per SITE (AGL-1775).\n const registerCap = Aglyn.checkHostRegisterQuota(org, hostId, registers.length).limit\n const withinCap = CommerceModel.registersWithinCap(registers, registerCap)\n const usableRegisters = planReady ? registers.filter((r: any) => withinCap.has(r.$id)) : []\n /*\n * The stays a sale can be charged to, asked for BY STATUS (AGL-3321).\n */\n const { data: reservationDocs } = useFirestoreCollection<any>(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'reservations'),\n where('status', '==', 'checked_in'),\n limit(100),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const openStays = reservationDocs ?? []\n\n const [lines, setLines] = useState<RegisterLine[]>([])\n const [discountPct, setDiscountPct] = useState(0)\n // The customer the lookup attached (AGL-3609); their email is the sale's.\n const [customer, setCustomer] = useState<PosSelectedCustomer | null>(null)\n const customerEmail = customer?.email ?? ''\n const [locationId, setLocationId] = useState('')\n const [registerId, setRegisterId] = useState('')\n useEffect(() => {\n if (registerId || usableRegisters.length === 0) return\n const first = usableRegisters[0]\n setRegisterId(first.$id)\n if (first.locationId) setLocationId(first.locationId)\n }, [usableRegisters, registerId])\n const registerName = String(\n usableRegisters.find((register: any) => register.$id === registerId)?.name ?? '',\n )\n // Who is ringing (AGL-3609): a PIN-switched cashier, and the idle lock.\n const opsSettings = usePosOpsSettings(hostId)\n const cashier = usePosCashier({\n hostId,\n registerId,\n autoLockMinutes: opsSettings.autoLockMinutes,\n })\n // The last completed sale, whose receipt can still be printed (AGL-3609).\n const [lastReceipt, setLastReceipt] = useState<{ orderId: string } | null>(null)\n\n const [context, setContext] = useState<PosRegisterContext | null>(null)\n // Keyed on the uid, not the user object: a session refresh hands back a\n // new object for the same person, and re-reading the context on every one\n // would re-render the register in a loop.\n const userRef = useRef(user)\n userRef.current = user\n const uid = user?.uid ?? ''\n useEffect(() => {\n const signedIn = userRef.current\n if (!signedIn) return\n let active = true\n posRegisterContext(signedIn, hostId)\n .then((answer) => {\n // Only a whole answer: a register that half-knows its tenders would\n // offer one the server then refuses.\n if (active && answer?.settings && answer?.terminal) setContext(answer)\n })\n .catch(() => undefined)\n return () => {\n active = false\n }\n }, [uid, hostId])\n\n /** The open sale, once the basket has been priced and payment started. */\n const [sale, setSale] = useState<PosSaleSummary | null>(null)\n const [saleLines, setSaleLines] = useState<RegisterLine[]>([])\n const [opening, setOpening] = useState(false)\n const [sheetOpen, setSheetOpen] = useState(false)\n const display = usePosDisplay(user, hostId, registerId)\n\n /**\n * One key per basket (AGL-1691): minted on the first Charge and retired\n * whenever the basket changes, so a retried Charge finds the same sale and\n * ringing the same coffee twice is two sales.\n */\n const attemptKey = useRef('')\n const fill = useViewportFill({ min: 480 })\n useEffect(() => {\n attemptKey.current = ''\n }, [lines, discountPct])\n\n const products = useMemo(\n () =>\n [...(productDocs ?? [])].map((product: any) => ({\n ...CommerceModel.liftLegacyProduct(product),\n $id: product.$id,\n })),\n [productDocs],\n )\n /*\n * THE OFFLINE REGISTER (AGL-3625): the catalog and the site's offline rules\n * kept on this device, the queue of cash sales rung without a connection,\n * and the sync that records them once it returns.\n */\n const loadCatalog = useCallback(\n async () =>\n (\n await getDocs(\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(posProductPlan({})),\n limit(POS_GRID_CEILING),\n ),\n )\n ).docs.map((snapshot) => ({ ...(snapshot.data() as Record<string, unknown>), $id: snapshot.id })),\n [firestore, hostId],\n )\n const liveRegister = usableRegisters.find((register: any) => register.$id === registerId)\n const offline = usePosOffline({\n hostId,\n user,\n registerId,\n openShiftId: liveRegister ? (liveRegister.openShiftId ?? null) : undefined,\n locationId,\n ...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {}),\n liveProducts: products,\n loadCatalog,\n })\n const [offlineCheckout, setOfflineCheckout] = useState(false)\n /** Open sales left unpaid when the connection dropped, voided once it returns. */\n const strandedSales = useRef<string[]>([])\n useEffect(() => {\n if (offline.offline || !user || !strandedSales.current.length) return\n const orderIds = strandedSales.current.splice(0)\n for (const orderId of orderIds) {\n void posTender(user, hostId, orderId, 'void').catch(() => undefined)\n }\n }, [offline.offline, user, hostId])\n const sellProducts = useMemo(\n () => (offline.offline && offline.ready ? offline.gridProducts(search, categoryId, POS_QUICK_KEYS) : products),\n [offline, search, categoryId, products],\n )\n const productsById = useMemo(\n () => new Map<string, any>(sellProducts.map((product: any) => [product.$id, product] as const)),\n [sellProducts],\n )\n /** AGL-2357: warns, never blocks. */\n const shortfalls = useMemo(\n () =>\n lines.map((line) => {\n const product: any = productsById.get(line.productId)\n if (!product) return null\n return CommerceModel.stockShortfall(\n product,\n line.variantId ?? product.variants?.[0]?.id,\n line.quantity,\n )\n }),\n [lines, productsById],\n )\n\n const itemsCents = lines.reduce((sum, line) => sum + line.unitAmountCents * line.quantity, 0)\n const discountCents = Math.round((itemsCents * discountPct) / 100)\n const estimateCents = itemsCents - discountCents\n const units = lines.reduce((sum, line) => sum + line.quantity, 0)\n\n const notify = useCallback(\n (message: string, variant: 'success' | 'error' | 'warning' | 'info') => {\n enqueueSnackbar(message, { variant, persist: false, allowDuplicate: true })\n },\n [enqueueSnackbar],\n )\n\n /**\n * A pairing code for a customer display or a self-service kiosk (AGL-3623),\n * through the same flow the POS devices card offers (AGL-3712).\n */\n const onPairingError = useCallback((message: string) => notify(message, 'error'), [notify])\n const pairingFlow = usePosPairing({ user, hostId, onError: onPairingError })\n\n /**\n * Adds a line, or more of an identical one: the same product, variant and\n * modifiers merge, so two oat lattes are one line of two and an oat latte\n * beside a whole-milk one stays two lines.\n */\n const addProduct = useCallback(\n (product: any, variant?: any, modifiers: CommerceModel.ModifierSelection[] = [], quantity = 1) => {\n const next = registerLineFor(product, {\n variant: variant ?? product.variants[0],\n modifiers,\n quantity,\n })\n setLines((prev) => {\n const existing = prev.find((line) => lineKey(line) === lineKey(next))\n if (existing) {\n return prev.map((line) =>\n line === existing\n ? { ...line, quantity: Math.min(99, line.quantity + next.quantity) }\n : line,\n )\n }\n return [...prev, next]\n })\n },\n [],\n )\n\n /** The item sheet: a product to add, or a basket line to change. */\n const [itemSheet, setItemSheet] = useState<{\n product: any\n editIndex?: number\n initial?: { variantId?: string; modifiers?: CommerceModel.ModifierSelection[]; quantity: number }\n } | null>(null)\n // Every product rung up this sale, so a line can be reopened after the\n // grid has moved on to another category or search.\n const productCache = useRef(new Map<string, any>())\n const tapProduct = useCallback(\n (product: any, variant?: any) => {\n productCache.current.set(product.$id, product)\n if (posItemNeedsChoice(product) && !(variant && CommerceModel.productModifierGroups(product).length === 0)) {\n setItemSheet({\n product,\n ...(variant ? { initial: { variantId: variant.id, quantity: 1 } } : {}),\n })\n return\n }\n addProduct(product, variant)\n },\n [addProduct],\n )\n const basketCounts = useMemo(() => {\n const counts = new Map<string, number>()\n for (const line of lines) counts.set(line.productId, (counts.get(line.productId) ?? 0) + line.quantity)\n return counts\n }, [lines])\n\n /**\n * The barcode wedge: a LOOKUP against the whole catalog (AGL-2501),\n * barcode first, and a miss says so.\n */\n const lookupCode = useCallback(async (scanned: string) => {\n const needle = scanned.trim().toLowerCase()\n if (!needle || sale) return\n if (offline.offline) {\n const found = offline.findByCode(needle)\n if (!found) return void notify(`No product matches “${scanned.trim()}”`, 'warning')\n tapProduct(found.product, found.variant)\n setSearch('')\n return\n }\n const lookup = async (field: 'barcodes' | 'skus') => {\n const found = await getDocs(\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(posProductPlan({ code: { field, value: needle } })),\n limit(1),\n ),\n )\n return found.docs[0]\n }\n let hit: Awaited<ReturnType<typeof lookup>>\n try {\n hit = (await lookup('barcodes')) ?? (await lookup('skus'))\n } catch (error) {\n console.error(error)\n offline.reportNetworkFailure()\n return void notify('Could not reach the catalog — try again', 'warning')\n }\n if (!hit) return void notify(`No product matches “${scanned.trim()}”`, 'warning')\n const product = { ...CommerceModel.liftLegacyProduct(hit.data() as any), $id: hit.id }\n const variant =\n product.variants.find(\n (item: any) =>\n item.barcode?.trim().toLowerCase() === needle || item.sku?.trim().toLowerCase() === needle,\n ) ?? product.variants[0]\n // A scanned variant is the variant; a product with modifiers still asks\n // for them, with that variant already picked.\n tapProduct(product, variant)\n setSearch('')\n }, [sale, firestore, hostId, tapProduct, notify, offline])\n const handleSearchEnter = useCallback(() => lookupCode(search), [lookupCode, search])\n // A scanner fired while focus is on a product or a button (AGL-3619), and\n // the camera; neither while a sale is taking payment or an item is open.\n useScannerWedge((code) => void lookupCode(code), !sale && !itemSheet)\n const scanAdornment = useMemo(\n () => <ScanAdornment label=\"Scan a barcode with the camera\" onScan={(code) => void lookupCode(code)} />,\n [lookupCode],\n )\n\n /** Prices the basket on the server and opens the sale for payment. */\n // A ref, not `opening`: two taps inside one React batch both read the\n // pre-click state, and only a ref is written before the second reads it\n // (the AGL-1682 lesson).\n const chargeInFlight = useRef(false)\n const charge = useCallback(async () => {\n if (chargeInFlight.current || lines.length === 0 || !user) return\n if (!registerId) return void notify('Select a register before taking payment', 'warning')\n // Offline, the basket rings as a cash sale kept on this register (AGL-3625).\n if (offline.offline) {\n if (!offline.ready) return void notify(offline.unavailableReason ?? 'Offline selling is unavailable', 'warning')\n setOfflineCheckout(true)\n return\n }\n if (!attemptKey.current) attemptKey.current = newAttemptKey()\n chargeInFlight.current = true\n setOpening(true)\n try {\n const opened = await openPosSale(user, attemptKey.current, {\n hostId,\n registerId,\n lines,\n discountPct,\n ...(customerEmail ? { customerEmail } : {}),\n ...(customer ? { customer } : {}),\n ...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {}),\n ...(locationId ? { locationId } : {}),\n })\n setSaleLines(lines)\n setSale({\n orderId: opened.orderId,\n status: 'pending',\n totalCents: opened.totals.totalCents,\n paidCents: 0,\n dueCents: opened.totals.totalCents,\n tenderableCents: opened.totals.totalCents,\n tipCents: 0,\n payments: [],\n })\n setSheetOpen(true)\n } catch (error) {\n if (error instanceof PosRequestError) {\n notify(error.message, 'error')\n } else {\n // The request never reached the server: the register is offline.\n offline.reportNetworkFailure()\n notify('The register lost its connection. Charge again to take cash offline.', 'warning')\n }\n } finally {\n chargeInFlight.current = false\n setOpening(false)\n }\n }, [lines, user, registerId, hostId, discountPct, customerEmail, customer, cashier.assertion, locationId, notify, offline])\n\n const resetSale = useCallback(() => {\n if (sale?.status === 'paid') setLastReceipt({ orderId: sale.orderId })\n setSale(null)\n setSaleLines([])\n setLines([])\n setDiscountPct(0)\n setCustomer(null)\n setSheetOpen(false)\n }, [sale])\n\n // The customer display mirrors the basket while nothing else is on it.\n const mirrored = sale ? saleLines : lines\n // Whether the display was last left showing a basket. A paid sale leaves it\n // on the thank-you the server wrote, which an empty new basket must not\n // cut short with the idle screen; the next item added takes it over.\n // True at first, so a register that opens empty clears whatever a previous\n // session left on the screen.\n const displayShowsBasket = useRef(true)\n // The tip picked for the payment about to be taken; the ledger has it only\n // once that payment is recorded. Gone with the sale.\n const [pendingTipCents, setPendingTipCents] = useState(0)\n useEffect(() => {\n if (!sale || sale.status === 'paid') setPendingTipCents(0)\n }, [sale])\n useEffect(() => {\n if (sale?.status === 'paid') displayShowsBasket.current = false\n }, [sale?.status])\n useEffect(() => {\n if (!display.connected || display.asking) return\n if (sale?.payments.some((payment) => payment.status === 'pending' && payment.method === 'card_present')) {\n return\n }\n if (sale?.status === 'paid') return\n if (!mirrored.length && !displayShowsBasket.current) return\n const timer = setTimeout(() => {\n displayShowsBasket.current = mirrored.length > 0\n void display.show(\n mirrored.length\n ? {\n mode: 'cart',\n cart: {\n lines: mirrored.map((line) => ({\n name: line.name,\n ...(line.variantLabel ? { variantLabel: line.variantLabel } : {}),\n quantity: line.quantity,\n amountCents: line.unitAmountCents * line.quantity,\n })),\n itemsCents,\n discountCents,\n taxCents: sale ? Math.max(0, sale.totalCents - estimateCents) : 0,\n totalCents: sale ? sale.totalCents : estimateCents,\n ...(sale\n ? {\n paidCents: sale.paidCents,\n dueCents: sale.dueCents,\n tipCents: posDisplayTipCents(sale, pendingTipCents),\n }\n : {}),\n },\n }\n : { mode: 'idle' },\n )\n }, 400)\n return () => clearTimeout(timer)\n }, [display, mirrored, sale, itemsCents, discountCents, estimateCents, pendingTipCents])\n\n const registersHref = posRegistersSettingsHref(basePath)\n const registerPicker = !planReady ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your plan…'}\n </Typography>\n ) : usableRegisters.length === 0 ? (\n registers.length > 0 ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {'Your registers exceed your plan — remove extras or upgrade in Billing to take payments.'}\n </Typography>\n ) : (\n // A way there, not a path to follow by hand (AGL-3712).\n <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Typography variant=\"body2\" color=\"warning.main\">\n {'No POS register yet. Add one before taking payments.'}\n </Typography>\n {registersHref ? (\n <Button size=\"small\" variant=\"outlined\" href={registersHref}>\n {'Add a register'}\n </Button>\n ) : null}\n </Stack>\n )\n ) : usableRegisters.length > 1 ? (\n <TextField\n label=\"Register\"\n value={registerId}\n onChange={(event) => setRegisterId(event.target.value)}\n size=\"small\"\n select\n disabled={Boolean(sale)}\n >\n {usableRegisters.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {usableRegisters[0]?.name}\n </Typography>\n )\n\n /**\n * On a narrow screen the register's bar owns the bottom edge, so it moves\n * the console's floating launchers clear of itself through the shell's\n * `--aglyn-dock-inset-bottom` seam; a launcher left in the corner sat on\n * top of Charge.\n */\n const bottomBarRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n const node = bottomBarRef.current\n if (wide || !node) return undefined\n const root = document.documentElement\n const property = '--aglyn-dock-inset-bottom'\n const publish = () => {\n root.style.setProperty(property, `${Math.round(node.getBoundingClientRect().height) + 20}px`)\n }\n publish()\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(publish)\n observer?.observe(node)\n return () => {\n observer?.disconnect()\n root.style.removeProperty(property)\n }\n }, [wide])\n\n const registerPanel = (\n <Stack spacing={1.5} sx={{ minHeight: 0, flex: 1 }}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"h6\" sx={{ flex: 1 }}>\n {'Register'}\n </Typography>\n {registerId ? (\n <Button\n size=\"small\"\n onClick={() => void pairingFlow.open(registerId, 'display')}\n >\n {display.connected ? 'Display connected' : 'Pair display'}\n </Button>\n ) : null}\n </Stack>\n {registerPicker}\n {(locationDocs?.length ?? 0) > 1 ? (\n <TextField\n label=\"Location\"\n value={locationId}\n onChange={(event) => setLocationId(event.target.value)}\n size=\"small\"\n select\n disabled={Boolean(sale)}\n >\n {(locationDocs ?? []).map((location: any) => (\n <MenuItem key={location.$id} value={location.$id}>\n {location.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {registerId ? (\n <PosOperationsBar\n hostId={hostId}\n registerId={registerId}\n {...(registerName ? { registerName } : {})}\n cashier={cashier}\n onExchange={(returned) =>\n setCustomer(\n returned.email || returned.name\n ? { kind: 'none', id: '', name: returned.name ?? '', email: returned.email, phone: null }\n : null,\n )\n }\n />\n ) : null}\n <PosCartPanel\n lines={sale ? saleLines : lines}\n shortfalls={sale ? [] : shortfalls}\n onQuantity={(index, quantity) =>\n setLines((prev) =>\n quantity <= 0\n ? prev.filter((_line, at) => at !== index)\n : prev.map((line, at) => (at === index ? { ...line, quantity: Math.min(99, quantity) } : line)),\n )\n }\n onRemove={(index) => setLines((prev) => prev.filter((_line, at) => at !== index))}\n onEdit={(index) => {\n const line = lines[index]\n const product = line\n ? (productCache.current.get(line.productId) ?? productsById.get(line.productId))\n : undefined\n if (!line || !product) return\n setItemSheet({\n product,\n editIndex: index,\n initial: {\n ...(line.variantId ? { variantId: line.variantId } : {}),\n ...(line.modifiers ? { modifiers: line.modifiers } : {}),\n quantity: line.quantity,\n },\n })\n }}\n discountPct={discountPct}\n onDiscountPct={setDiscountPct}\n customer={\n sale ? null : <PosCustomerLookup hostId={hostId} value={customer} onChange={setCustomer} />\n }\n locked={Boolean(sale)}\n />\n {sale && user ? (\n sale.status === 'paid' ? (\n <PosReceiptPanel\n user={user}\n hostId={hostId}\n sale={sale}\n context={context}\n display={display}\n onNewSale={resetSale}\n registerId={registerId}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n notify={notify}\n />\n ) : (\n <PosTenderPanel\n user={user}\n hostId={hostId}\n registerId={registerId}\n sale={sale}\n context={context}\n stays={openStays}\n display={display}\n onSale={setSale}\n onVoided={() => {\n setSale(null)\n setSaleLines([])\n }}\n onTipChange={setPendingTipCents}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n notify={notify}\n offline={offline.offline}\n {...(offline.ready\n ? {\n onSellOffline: () => {\n // The server's open sale took no payment; it is voided once\n // the connection returns, and the basket rings offline.\n strandedSales.current.push(sale.orderId)\n setSale(null)\n setSaleLines([])\n setOfflineCheckout(true)\n },\n }\n : {})}\n />\n )\n ) : (\n <>\n <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>\n <Typography variant=\"h6\">{'Due'}</Typography>\n <Typography variant=\"h6\">{usd(estimateCents)}</Typography>\n </Box>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Tax is added when you charge.'}\n </Typography>\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={opening || lines.length === 0 || !registerId}\n onClick={() => void charge()}\n sx={{ minHeight: 56 }}\n >\n {opening\n ? 'Pricing…'\n : offline.offline\n ? `Cash ${usd(offline.totalsFor(lines, discountPct)?.totalCents ?? estimateCents)} (offline)`\n : `Charge ${usd(estimateCents)}`}\n </Button>\n {lastReceipt ? (\n <PosLastReceipt\n hostId={hostId}\n orderId={lastReceipt.orderId}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n />\n ) : null}\n </>\n )}\n </Stack>\n )\n\n return (\n <>\n <NextPageTitle screen={'POS'} />\n <Box\n ref={fill.ref}\n sx={{\n display: 'flex',\n // From under the console's header, nav and page title down to\n // where the page's padding and footer begin, so the whole page fits\n // the window (AGL-3679, AGL-3710).\n height: fill.height,\n overflow: 'hidden',\n }}\n >\n <Box sx={{ flex: 1, p: 2, overflowY: 'auto', pb: wide ? 2 : 12 }}>\n <Box sx={{ mb: 2, '&:empty': { display: 'none' } }}>\n <PosOfflineBanner offline={offline} />\n </Box>\n {/* \"Pay at counter\" orders from this register's kiosks (AGL-3623). */}\n {registerId ? (\n <PosKioskQueue\n user={user}\n hostId={hostId}\n registerId={registerId}\n disabled={Boolean(sale)}\n onTake={(next, nextLines) => {\n setSaleLines(nextLines)\n setSale(next)\n setSheetOpen(true)\n }}\n notify={notify}\n />\n ) : null}\n {/* Orders other channels send to the counter (AGL-3644). */}\n {WidgetSlot ? <PosOrdersZone renderer={WidgetSlot} hostId={hostId} registerId={registerId || null} /> : null}\n <PosProductGrid\n search={search}\n onSearch={setSearch}\n onSearchEnter={() => void handleSearchEnter()}\n scanAdornment={scanAdornment}\n categories={(categoryDocs ?? []).map((category: any) => ({\n $id: category.$id,\n name: String(category.name ?? 'Category'),\n }))}\n categoryId={categoryId}\n onCategory={setCategoryId}\n notices={gridPlan.notices}\n hostId={hostId}\n products={sellProducts}\n basketCounts={basketCounts}\n onTap={(product) => {\n if (sale) return void notify('Finish or void the open sale first', 'info')\n tapProduct(product)\n }}\n />\n </Box>\n {wide ? (\n <Box\n sx={{\n width: { md: 400, lg: 440 },\n borderLeft: 1,\n borderColor: 'divider',\n display: 'flex',\n flexDirection: 'column',\n p: 2,\n overflowY: 'auto',\n }}\n >\n {registerPanel}\n </Box>\n ) : null}\n </Box>\n {!wide ? (\n <>\n <Box\n ref={bottomBarRef}\n sx={{\n position: 'fixed',\n left: 0,\n right: 0,\n bottom: 0,\n p: 1.5,\n bgcolor: 'background.paper',\n borderTop: 1,\n borderColor: 'divider',\n display: 'flex',\n gap: 1,\n alignItems: 'center',\n zIndex: theme.zIndex.appBar,\n }}\n >\n <Badge badgeContent={units} color=\"primary\">\n <Button\n variant=\"outlined\"\n onClick={() => setSheetOpen(true)}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {sale ? 'Payment' : 'Cart'}\n </Button>\n </Badge>\n <Typography variant=\"h6\" sx={{ flex: 1, textAlign: 'right' }}>\n {usd(sale ? sale.dueCents : estimateCents)}\n </Typography>\n {!sale ? (\n <Button\n variant=\"contained\"\n disabled={opening || lines.length === 0 || !registerId}\n onClick={() => void charge()}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Charge'}\n </Button>\n ) : null}\n </Box>\n <Drawer\n anchor=\"bottom\"\n open={sheetOpen}\n onClose={() => setSheetOpen(false)}\n slotProps={{ paper: { sx: { maxHeight: '90dvh', p: 2, borderTopLeftRadius: 16, borderTopRightRadius: 16 } } }}\n >\n {registerPanel}\n </Drawer>\n </>\n ) : null}\n <PosItemDialog\n product={itemSheet?.product ?? null}\n initial={itemSheet?.initial}\n onClose={() => setItemSheet(null)}\n onConfirm={(choice) => {\n const sheet = itemSheet\n setItemSheet(null)\n if (!sheet) return\n if (sheet.editIndex === undefined) {\n addProduct(sheet.product, choice.variant, choice.modifiers, choice.quantity)\n return\n }\n const at = sheet.editIndex\n setLines((prev) =>\n prev.map((line, index) => (index === at ? registerLineFor(sheet.product, choice) : line)),\n )\n }}\n {...(itemSheet?.editIndex !== undefined\n ? {\n onRemove: () => {\n const at = itemSheet.editIndex\n setItemSheet(null)\n setLines((prev) => prev.filter((_line, index) => index !== at))\n },\n }\n : {})}\n />\n <PosOfflineCheckout\n open={offlineCheckout}\n offline={offline}\n hostId={hostId}\n lines={lines}\n discountPct={discountPct}\n customer={customer}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n onClose={() => setOfflineCheckout(false)}\n onRung={() => undefined}\n onDone={() => {\n setOfflineCheckout(false)\n setLines([])\n setDiscountPct(0)\n setCustomer(null)\n setSheetOpen(false)\n }}\n />\n {pairingFlow.dialog}\n </>\n )\n}\nPosConsolePage.displayName = 'PosConsolePage'\n\nexport default PosConsolePage\n"],"names":["Aglyn","CommerceModel","PRODUCT_LIST_BASE","PRODUCT_LIST_QUERY","NextPageTitle","useSnackbar","planListQuery","useViewportFill","nameSearchNormalizers","Badge","Box","Button","Drawer","MenuItem","Stack","TextField","Typography","useMediaQuery","useTheme","collection","getDocs","limit","query","where","memo","useCallback","useEffect","useMemo","useRef","useState","useFirestore","useUser","useFirestoreCollection","listQueryConstraints","useOrgPlan","newAttemptKey","openPosSale","posRegisterContext","posTender","PosRequestError","usd","PosCartPanel","ScanAdornment","useScannerWedge","PosCustomerLookup","PosLastReceipt","PosOperationsBar","usePosCashier","usePosOpsSettings","POS_QUICK_KEYS","POS_TOUCH_PX","PosProductGrid","PosItemDialog","posItemNeedsChoice","PosReceiptPanel","PosTenderPanel","PosKioskQueue","posDisplayTipCents","usePosDisplay","posRegistersSettingsHref","usePosPairing","useConsoleWidgetSlot","POS_ORDERS_ZONE","PosOfflineBanner","PosOfflineCheckout","usePosOffline","SELLABLE","field","op","value","POS_GRID_CEILING","posProductPlan","options","typed","search","trim","plan","POS_GRID_QUERY","base","clauses","code","categoryId","quickKeys","filters","path","fields","column","kind","tokensPath","operators","POS_CATEGORY_KEY","registerLineFor","product","choice","variant","modifiers","quantity","resolved","resolveLineModifiers","picked","ok","label","lineLabelWithModifiers","Object","keys","length","values","join","undefined","productId","$id","id","variantId","name","variantLabel","unitAmountCents","Math","round","Number","priceUsd","extraCents","lineKey","line","modifierSelectionKey","PosOrdersZone","props","renderer","Renderer","hostId","registerId","slot","orgId","PosConsolePage","basePath","liveRegister","usableRegisters","offline","WidgetSlot","firestore","data","user","enqueueSnackbar","theme","wide","breakpoints","up","setSearch","setCategoryIdState","window","localStorage","getItem","setCategoryId","setItem","gridPlan","productDocs","idField","categoryDocs","locationDocs","registerDocs","org","ready","planReady","registers","sort","a","b","String","localeCompare","registerCap","checkHostRegisterQuota","withinCap","registersWithinCap","filter","r","has","reservationDocs","openStays","lines","setLines","discountPct","setDiscountPct","customer","setCustomer","customerEmail","email","locationId","setLocationId","setRegisterId","first","registerName","find","register","opsSettings","cashier","autoLockMinutes","lastReceipt","setLastReceipt","context","setContext","userRef","current","uid","signedIn","active","then","answer","settings","terminal","catch","sale","setSale","saleLines","setSaleLines","opening","setOpening","sheetOpen","setSheetOpen","display","attemptKey","fill","min","products","map","liftLegacyProduct","loadCatalog","docs","snapshot","openShiftId","assertion","cashierAssertion","liveProducts","offlineCheckout","setOfflineCheckout","strandedSales","orderIds","splice","orderId","sellProducts","gridProducts","productsById","Map","shortfalls","get","stockShortfall","variants","itemsCents","reduce","sum","discountCents","estimateCents","units","notify","message","persist","allowDuplicate","onPairingError","pairingFlow","onError","addProduct","next","prev","existing","itemSheet","setItemSheet","productCache","tapProduct","set","productModifierGroups","initial","basketCounts","counts","lookupCode","scanned","needle","toLowerCase","found","findByCode","lookup","hit","error","console","reportNetworkFailure","item","barcode","sku","handleSearchEnter","scanAdornment","onScan","chargeInFlight","charge","unavailableReason","opened","status","totalCents","totals","paidCents","dueCents","tenderableCents","tipCents","payments","resetSale","mirrored","displayShowsBasket","pendingTipCents","setPendingTipCents","connected","asking","some","payment","method","timer","setTimeout","show","mode","cart","amountCents","taxCents","max","clearTimeout","registersHref","registerPicker","color","spacing","sx","alignItems","size","href","onChange","event","target","select","disabled","Boolean","bottomBarRef","node","root","document","documentElement","property","publish","style","setProperty","getBoundingClientRect","height","observer","ResizeObserver","observe","disconnect","removeProperty","registerPanel","minHeight","flex","direction","onClick","open","location","onExchange","returned","phone","onQuantity","index","_line","at","onRemove","onEdit","editIndex","onDiscountPct","locked","onNewSale","cashierName","stays","onSale","onVoided","onTipChange","onSellOffline","push","justifyContent","totalsFor","screen","ref","overflow","p","overflowY","pb","mb","onTake","nextLines","onSearch","onSearchEnter","categories","category","onCategory","notices","onTap","width","md","lg","borderLeft","borderColor","flexDirection","position","left","right","bottom","bgcolor","borderTop","gap","zIndex","appBar","badgeContent","textAlign","anchor","onClose","slotProps","paper","maxHeight","borderTopLeftRadius","borderTopRightRadius","onConfirm","sheet","onRung","onDone","dialog","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-page.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport * as CommerceModel from '../../model'\nimport {\n PRODUCT_LIST_BASE,\n PRODUCT_LIST_QUERY,\n} from '../../constants/product-list-query'\nimport { NextPageTitle } from '@aglyn/shared-ui-next/contexts/next-page-title-provider'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport type { ListFilterRequest } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport { planListQuery } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { useViewportFill } from '@aglyn/shared-ui-jsx/hooks/use-viewport-fill'\nimport { nameSearchNormalizers } from '@aglyn/aglyn/app-utils/name-search'\nimport {\n Badge,\n Box,\n Button,\n Drawer,\n MenuItem,\n Stack,\n TextField,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport {\n collection,\n getDocs,\n limit,\n query,\n where,\n} from 'firebase/firestore'\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { listQueryConstraints } from '@aglyn/tenant-feature-instance/hooks/use-list-query'\nimport { useOrgPlan } from '@aglyn/tenant-feature-instance'\nimport {\n newAttemptKey,\n openPosSale,\n posRegisterContext,\n posTender,\n PosRequestError,\n usd,\n type PosRegisterContext,\n type PosSaleSummary,\n} from './pos/pos-api'\nimport { PosCartPanel, type RegisterLine } from './pos/pos-cart-panel.component'\nimport { ScanAdornment } from '../../barcode/scan-button.component'\nimport { useScannerWedge } from '../../barcode/scanner-wedge'\nimport {\n PosCustomerLookup,\n PosLastReceipt,\n PosOperationsBar,\n usePosCashier,\n usePosOpsSettings,\n type PosSelectedCustomer,\n} from './pos-ops/register-ops'\nimport { POS_QUICK_KEYS, POS_TOUCH_PX, PosProductGrid } from './pos/pos-product-grid.component'\nimport { PosItemDialog, posItemNeedsChoice, type PosItemChoice } from './pos/pos-item-dialog.component'\nimport { PosReceiptPanel } from './pos/pos-receipt-panel.component'\nimport { PosTenderPanel } from './pos/pos-tender-panel.component'\nimport { PosKioskQueue } from './pos/pos-kiosk-queue.component'\nimport { posDisplayTipCents, usePosDisplay } from './pos/use-pos-display'\nimport { posRegistersSettingsHref, usePosPairing } from './pos/pos-pairing.component'\nimport {\n type ConsoleWidgetSlotRenderer,\n useConsoleWidgetSlot,\n} from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport { POS_ORDERS_ZONE } from './pos-zones'\nimport { PosOfflineBanner, PosOfflineCheckout, usePosOffline } from './pos-offline/register-offline'\n\n/** The till sells active products only; every read of the catalog asks it. */\nconst SELLABLE: ListFilterRequest = { field: 'status', op: 'equals', value: 'active' }\n\n/**\n * How many products the till's grid shows. The grid is a picker, not the\n * catalog: typing narrows it on the query, so a name reaches every product.\n */\nconst POS_GRID_CEILING = 500\n\n/**\n * The products hub's query (AGL-3321), narrowed to what the till may sell:\n * live products (`deletedAt == null`, the list's scope), `status == active`,\n * and any typed word as the search on `nameTokens` — or, for a scan, the\n * whole scanned code as a SKU or barcode clause. Every shape is one the hub's\n * composites already serve.\n */\nexport function posProductPlan(options: {\n search?: string\n code?: { field: 'barcodes' | 'skus'; value: string }\n /** A category chip (AGL-3607): served by the storefront's own composite. */\n categoryId?: string\n /** The Quick keys chip (AGL-3607): products marked `posQuickKey`. */\n quickKeys?: boolean\n}) {\n const typed = options.search?.trim()\n const plan = planListQuery(\n POS_GRID_QUERY,\n {\n base: PRODUCT_LIST_BASE,\n clauses: [\n SELLABLE,\n ...(options.code\n ? [{ field: options.code.field, op: 'contains', value: options.code.value }]\n : []),\n ...(options.categoryId\n ? [{ field: 'categoryIds', op: 'contains', value: options.categoryId }]\n : []),\n ],\n // A chip and a typed word are both array clauses, and Firestore takes\n // one: with a chip on, the word narrows by name prefix instead.\n search: typed && !options.categoryId ? [typed] : [],\n },\n nameSearchNormalizers,\n )\n // The Quick keys chip (AGL-3607) is a boolean equality the list planner\n // does not model, added beside the scope and status it composes with —\n // `deletedAt ==, status ==, posQuickKey ==, nameLower ASC` is declared in\n // the index file. A typed word searches the whole catalog instead: a\n // cashier who types is looking past the quick keys.\n if (options.quickKeys && !typed && !options.code) {\n return {\n ...plan,\n filters: [...plan.filters, { path: 'posQuickKey', op: '==', value: true }],\n } as typeof plan\n }\n return plan\n}\n\n/**\n * The grid's query: the products hub's, plus the category a chip picks\n * (AGL-3607). `categoryIds CONTAINS, nameLower ASC` is a composite the\n * storefront catalog already declares.\n */\nexport const POS_GRID_QUERY = {\n ...PRODUCT_LIST_QUERY,\n fields: [\n ...PRODUCT_LIST_QUERY.fields,\n {\n column: 'categoryIds',\n kind: 'exact' as const,\n path: 'categoryIds',\n tokensPath: 'categoryIds',\n operators: ['contains'],\n },\n ],\n} as typeof PRODUCT_LIST_QUERY\n\n/**\n * POS register (AGL-312, AGL-3607): a tablet-first sale surface — the\n * product grid with search, scan and category chips, the basket, and a\n * tender panel that takes one or more payments against an open sale (cash,\n * card reader, a native Tap to Pay bridge, a typed card, the QR link, gift\n * cards and room charges) until the balance is zero. A paired customer\n * display mirrors the basket and takes the tip and the receipt (AGL-3608).\n *\n * On a wide screen (900px and up) the grid and the register sit side by\n * side; below that the register is a bottom sheet behind a sticky total bar.\n */\n/*\n * `managePos` is NOT read here. The nav item in `plugin.ts` declares it and\n * the shell refuses the route before this component is constructed, so a\n * reader without the key never reaches this file and there is no unpermitted\n * state for it to render — the same arrangement the entitlement gate has.\n *\n * Re-adding a check off the `permissions` prop would be a second answer to a\n * settled question, and a laxer one: a prop absent because the map has not\n * landed reads as permitted here, while the shell holds the route on that\n * same condition rather than guessing. The server routes remain the\n * enforcement point for every sale and every payment.\n */\n/** Where a register device remembers the category chip it was left on. */\nconst POS_CATEGORY_KEY = 'aglyn.pos.category'\n\n/** The basket line an item-sheet choice makes: label and estimate from the product. */\nexport function registerLineFor(\n product: any,\n choice: PosItemChoice,\n): RegisterLine {\n const { variant, modifiers, quantity } = choice\n const resolved = CommerceModel.resolveLineModifiers(product, modifiers)\n const picked = resolved.ok ? resolved.modifiers : []\n const label = CommerceModel.lineLabelWithModifiers(\n Object.keys(variant.options ?? {}).length\n ? Object.values(variant.options ?? {}).join(' / ')\n : undefined,\n picked,\n )\n return {\n productId: product.$id,\n ...(variant.id !== 'default' ? { variantId: variant.id } : {}),\n name: product.name,\n ...(label ? { variantLabel: label } : {}),\n unitAmountCents:\n Math.round(Number(variant.priceUsd) * 100) + (resolved.ok ? resolved.extraCents : 0),\n quantity,\n ...(modifiers.length ? { modifiers } : {}),\n }\n}\n\n/** Same product, variant and choices: the lines that merge into one. */\nfunction lineKey(line: Pick<RegisterLine, 'productId' | 'variantId' | 'modifiers'>): string {\n return `${line.productId}:${line.variantId ?? ''}:${CommerceModel.modifierSelectionKey(line.modifiers)}`\n}\n\n/**\n * The register's zone (AGL-3644), drawn again only when what it is handed\n * changes: the till redraws on every tap, and the shell's renderer is not\n * memoized (the order dialog's reasoning).\n */\nconst PosOrdersZone = memo(function PosOrdersZone(props: {\n renderer: ConsoleWidgetSlotRenderer\n hostId: string\n registerId: string | null\n}) {\n const { renderer: Renderer, hostId, registerId } = props\n return <Renderer slot={POS_ORDERS_ZONE.id} hostId={hostId} orgId={undefined} registerId={registerId} />\n})\n\nexport function PosConsolePage({ hostId, basePath }: ConsolePluginPageProps) {\n const WidgetSlot = useConsoleWidgetSlot()\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const theme = useTheme()\n const wide = useMediaQuery(theme.breakpoints.up('md'))\n\n const [search, setSearch] = useState('')\n // The chip a register opens on is remembered per device: a counter that\n // rings from its quick keys reopens on them.\n const [categoryId, setCategoryIdState] = useState(() => {\n try {\n return window.localStorage.getItem(POS_CATEGORY_KEY) ?? ''\n } catch {\n return ''\n }\n })\n const setCategoryId = useCallback((id: string) => {\n setCategoryIdState(id)\n try {\n window.localStorage.setItem(POS_CATEGORY_KEY, id)\n } catch {\n // Storage blocked: the chip still works for this visit.\n }\n }, [])\n const gridPlan = useMemo(\n () =>\n categoryId === POS_QUICK_KEYS\n ? posProductPlan({ search, quickKeys: true })\n : posProductPlan({ search, categoryId }),\n [search, categoryId],\n )\n const { data: productDocs } = useFirestoreCollection<any>(\n /*\n * The till's grid, narrowed by the QUERY rather than by the rows it\n * happened to fetch (AGL-2501, AGL-2292, AGL-3321): the first five\n * hundred SELLABLE products by name, and a typed name reaches the whole\n * catalog. The scan does not come through here — see `handleSearchEnter`.\n */\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(gridPlan),\n limit(POS_GRID_CEILING),\n ),\n [firestore, hostId, gridPlan],\n { idField: '$id' },\n )\n const { data: categoryDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'productCategories'), limit(30)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: locationDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'locations'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: registerDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'registers'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { org, ready: planReady } = useOrgPlan(hostId)\n const registers = [...(registerDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n // Only registers within the plan cap can transact (AGL-482), and not until\n // the org doc has arrived (AGL-1064). Per SITE (AGL-1775).\n const registerCap = Aglyn.checkHostRegisterQuota(org, hostId, registers.length).limit\n const withinCap = CommerceModel.registersWithinCap(registers, registerCap)\n const usableRegisters = planReady ? registers.filter((r: any) => withinCap.has(r.$id)) : []\n /*\n * The stays a sale can be charged to, asked for BY STATUS (AGL-3321).\n */\n const { data: reservationDocs } = useFirestoreCollection<any>(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'reservations'),\n where('status', '==', 'checked_in'),\n limit(100),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const openStays = reservationDocs ?? []\n\n const [lines, setLines] = useState<RegisterLine[]>([])\n const [discountPct, setDiscountPct] = useState(0)\n // The customer the lookup attached (AGL-3609); their email is the sale's.\n const [customer, setCustomer] = useState<PosSelectedCustomer | null>(null)\n const customerEmail = customer?.email ?? ''\n const [locationId, setLocationId] = useState('')\n const [registerId, setRegisterId] = useState('')\n useEffect(() => {\n if (registerId || usableRegisters.length === 0) return\n const first = usableRegisters[0]\n setRegisterId(first.$id)\n if (first.locationId) setLocationId(first.locationId)\n }, [usableRegisters, registerId])\n const registerName = String(\n usableRegisters.find((register: any) => register.$id === registerId)?.name ?? '',\n )\n // Who is ringing (AGL-3609): a PIN-switched cashier, and the idle lock.\n const opsSettings = usePosOpsSettings(hostId)\n const cashier = usePosCashier({\n hostId,\n registerId,\n autoLockMinutes: opsSettings.autoLockMinutes,\n })\n // The last completed sale, whose receipt can still be printed (AGL-3609).\n const [lastReceipt, setLastReceipt] = useState<{ orderId: string } | null>(null)\n\n const [context, setContext] = useState<PosRegisterContext | null>(null)\n // Keyed on the uid, not the user object: a session refresh hands back a\n // new object for the same person, and re-reading the context on every one\n // would re-render the register in a loop.\n const userRef = useRef(user)\n userRef.current = user\n const uid = user?.uid ?? ''\n useEffect(() => {\n const signedIn = userRef.current\n if (!signedIn) return\n let active = true\n posRegisterContext(signedIn, hostId)\n .then((answer) => {\n // Only a whole answer: a register that half-knows its tenders would\n // offer one the server then refuses.\n if (active && answer?.settings && answer?.terminal) setContext(answer)\n })\n .catch(() => undefined)\n return () => {\n active = false\n }\n }, [uid, hostId])\n\n /** The open sale, once the basket has been priced and payment started. */\n const [sale, setSale] = useState<PosSaleSummary | null>(null)\n const [saleLines, setSaleLines] = useState<RegisterLine[]>([])\n const [opening, setOpening] = useState(false)\n const [sheetOpen, setSheetOpen] = useState(false)\n const display = usePosDisplay(user, hostId, registerId)\n\n /**\n * One key per basket (AGL-1691): minted on the first Charge and retired\n * whenever the basket changes, so a retried Charge finds the same sale and\n * ringing the same coffee twice is two sales.\n */\n const attemptKey = useRef('')\n const fill = useViewportFill({ min: 480 })\n useEffect(() => {\n attemptKey.current = ''\n }, [lines, discountPct])\n\n const products = useMemo(\n () =>\n [...(productDocs ?? [])].map((product: any) => ({\n ...CommerceModel.liftLegacyProduct(product),\n $id: product.$id,\n })),\n [productDocs],\n )\n /*\n * THE OFFLINE REGISTER (AGL-3625): the catalog and the site's offline rules\n * kept on this device, the queue of cash sales rung without a connection,\n * and the sync that records them once it returns.\n */\n const loadCatalog = useCallback(\n async () =>\n (\n await getDocs(\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(posProductPlan({})),\n limit(POS_GRID_CEILING),\n ),\n )\n ).docs.map((snapshot) => ({ ...(snapshot.data() as Record<string, unknown>), $id: snapshot.id })),\n [firestore, hostId],\n )\n const liveRegister = usableRegisters.find((register: any) => register.$id === registerId)\n const offline = usePosOffline({\n hostId,\n user,\n registerId,\n openShiftId: liveRegister ? (liveRegister.openShiftId ?? null) : undefined,\n locationId,\n ...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {}),\n liveProducts: products,\n loadCatalog,\n })\n const [offlineCheckout, setOfflineCheckout] = useState(false)\n /** Open sales left unpaid when the connection dropped, voided once it returns. */\n const strandedSales = useRef<string[]>([])\n useEffect(() => {\n if (offline.offline || !user || !strandedSales.current.length) return\n const orderIds = strandedSales.current.splice(0)\n for (const orderId of orderIds) {\n void posTender(user, hostId, orderId, 'void').catch(() => undefined)\n }\n }, [offline.offline, user, hostId])\n const sellProducts = useMemo(\n () => (offline.offline && offline.ready ? offline.gridProducts(search, categoryId, POS_QUICK_KEYS) : products),\n [offline, search, categoryId, products],\n )\n const productsById = useMemo(\n () => new Map<string, any>(sellProducts.map((product: any) => [product.$id, product] as const)),\n [sellProducts],\n )\n /** AGL-2357: warns, never blocks. */\n const shortfalls = useMemo(\n () =>\n lines.map((line) => {\n const product: any = productsById.get(line.productId)\n if (!product) return null\n return CommerceModel.stockShortfall(\n product,\n line.variantId ?? product.variants?.[0]?.id,\n line.quantity,\n )\n }),\n [lines, productsById],\n )\n\n const itemsCents = lines.reduce((sum, line) => sum + line.unitAmountCents * line.quantity, 0)\n const discountCents = Math.round((itemsCents * discountPct) / 100)\n const estimateCents = itemsCents - discountCents\n const units = lines.reduce((sum, line) => sum + line.quantity, 0)\n\n const notify = useCallback(\n (message: string, variant: 'success' | 'error' | 'warning' | 'info') => {\n enqueueSnackbar(message, { variant, persist: false, allowDuplicate: true })\n },\n [enqueueSnackbar],\n )\n\n /**\n * A pairing code for a customer display or a self-service kiosk (AGL-3623),\n * through the same flow the POS devices card offers (AGL-3712).\n */\n const onPairingError = useCallback((message: string) => notify(message, 'error'), [notify])\n const pairingFlow = usePosPairing({ user, hostId, onError: onPairingError })\n\n /**\n * Adds a line, or more of an identical one: the same product, variant and\n * modifiers merge, so two oat lattes are one line of two and an oat latte\n * beside a whole-milk one stays two lines.\n */\n const addProduct = useCallback(\n (product: any, variant?: any, modifiers: CommerceModel.ModifierSelection[] = [], quantity = 1) => {\n const next = registerLineFor(product, {\n variant: variant ?? product.variants[0],\n modifiers,\n quantity,\n })\n setLines((prev) => {\n const existing = prev.find((line) => lineKey(line) === lineKey(next))\n if (existing) {\n return prev.map((line) =>\n line === existing\n ? { ...line, quantity: Math.min(99, line.quantity + next.quantity) }\n : line,\n )\n }\n return [...prev, next]\n })\n },\n [],\n )\n\n /** The item sheet: a product to add, or a basket line to change. */\n const [itemSheet, setItemSheet] = useState<{\n product: any\n editIndex?: number\n initial?: { variantId?: string; modifiers?: CommerceModel.ModifierSelection[]; quantity: number }\n } | null>(null)\n // Every product rung up this sale, so a line can be reopened after the\n // grid has moved on to another category or search.\n const productCache = useRef(new Map<string, any>())\n const tapProduct = useCallback(\n (product: any, variant?: any) => {\n productCache.current.set(product.$id, product)\n if (posItemNeedsChoice(product) && !(variant && CommerceModel.productModifierGroups(product).length === 0)) {\n setItemSheet({\n product,\n ...(variant ? { initial: { variantId: variant.id, quantity: 1 } } : {}),\n })\n return\n }\n addProduct(product, variant)\n },\n [addProduct],\n )\n const basketCounts = useMemo(() => {\n const counts = new Map<string, number>()\n for (const line of lines) counts.set(line.productId, (counts.get(line.productId) ?? 0) + line.quantity)\n return counts\n }, [lines])\n\n /**\n * The barcode wedge: a LOOKUP against the whole catalog (AGL-2501),\n * barcode first, and a miss says so.\n */\n const lookupCode = useCallback(async (scanned: string) => {\n const needle = scanned.trim().toLowerCase()\n if (!needle || sale) return\n if (offline.offline) {\n const found = offline.findByCode(needle)\n if (!found) return void notify(`No product matches “${scanned.trim()}”`, 'warning')\n tapProduct(found.product, found.variant)\n setSearch('')\n return\n }\n const lookup = async (field: 'barcodes' | 'skus') => {\n const found = await getDocs(\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n ...listQueryConstraints(posProductPlan({ code: { field, value: needle } })),\n limit(1),\n ),\n )\n return found.docs[0]\n }\n let hit: Awaited<ReturnType<typeof lookup>>\n try {\n hit = (await lookup('barcodes')) ?? (await lookup('skus'))\n } catch (error) {\n console.error(error)\n offline.reportNetworkFailure()\n return void notify('Could not reach the catalog — try again', 'warning')\n }\n if (!hit) return void notify(`No product matches “${scanned.trim()}”`, 'warning')\n const product = { ...CommerceModel.liftLegacyProduct(hit.data() as any), $id: hit.id }\n const variant =\n product.variants.find(\n (item: any) =>\n item.barcode?.trim().toLowerCase() === needle || item.sku?.trim().toLowerCase() === needle,\n ) ?? product.variants[0]\n // A scanned variant is the variant; a product with modifiers still asks\n // for them, with that variant already picked.\n tapProduct(product, variant)\n setSearch('')\n }, [sale, firestore, hostId, tapProduct, notify, offline])\n const handleSearchEnter = useCallback(() => lookupCode(search), [lookupCode, search])\n // A scanner fired while focus is on a product or a button (AGL-3619), and\n // the camera; neither while a sale is taking payment or an item is open.\n useScannerWedge((code) => void lookupCode(code), !sale && !itemSheet)\n const scanAdornment = useMemo(\n () => <ScanAdornment label=\"Scan a barcode with the camera\" onScan={(code) => void lookupCode(code)} />,\n [lookupCode],\n )\n\n /** Prices the basket on the server and opens the sale for payment. */\n // A ref, not `opening`: two taps inside one React batch both read the\n // pre-click state, and only a ref is written before the second reads it\n // (the AGL-1682 lesson).\n const chargeInFlight = useRef(false)\n const charge = useCallback(async () => {\n if (chargeInFlight.current || lines.length === 0 || !user) return\n if (!registerId) return void notify('Select a register before taking payment', 'warning')\n // Offline, the basket rings as a cash sale kept on this register (AGL-3625).\n if (offline.offline) {\n if (!offline.ready) return void notify(offline.unavailableReason ?? 'Offline selling is unavailable', 'warning')\n setOfflineCheckout(true)\n return\n }\n if (!attemptKey.current) attemptKey.current = newAttemptKey()\n chargeInFlight.current = true\n setOpening(true)\n try {\n const opened = await openPosSale(user, attemptKey.current, {\n hostId,\n registerId,\n lines,\n discountPct,\n ...(customerEmail ? { customerEmail } : {}),\n ...(customer ? { customer } : {}),\n ...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {}),\n ...(locationId ? { locationId } : {}),\n })\n setSaleLines(lines)\n setSale({\n orderId: opened.orderId,\n status: 'pending',\n totalCents: opened.totals.totalCents,\n paidCents: 0,\n dueCents: opened.totals.totalCents,\n tenderableCents: opened.totals.totalCents,\n tipCents: 0,\n payments: [],\n })\n setSheetOpen(true)\n } catch (error) {\n if (error instanceof PosRequestError) {\n notify(error.message, 'error')\n } else {\n // The request never reached the server: the register is offline.\n offline.reportNetworkFailure()\n notify('The register lost its connection. Charge again to take cash offline.', 'warning')\n }\n } finally {\n chargeInFlight.current = false\n setOpening(false)\n }\n }, [lines, user, registerId, hostId, discountPct, customerEmail, customer, cashier.assertion, locationId, notify, offline])\n\n const resetSale = useCallback(() => {\n if (sale?.status === 'paid') setLastReceipt({ orderId: sale.orderId })\n setSale(null)\n setSaleLines([])\n setLines([])\n setDiscountPct(0)\n setCustomer(null)\n setSheetOpen(false)\n }, [sale])\n\n // The customer display mirrors the basket while nothing else is on it.\n const mirrored = sale ? saleLines : lines\n // Whether the display was last left showing a basket. A paid sale leaves it\n // on the thank-you the server wrote, which an empty new basket must not\n // cut short with the idle screen; the next item added takes it over.\n // True at first, so a register that opens empty clears whatever a previous\n // session left on the screen.\n const displayShowsBasket = useRef(true)\n // The tip picked for the payment about to be taken; the ledger has it only\n // once that payment is recorded. Gone with the sale.\n const [pendingTipCents, setPendingTipCents] = useState(0)\n useEffect(() => {\n if (!sale || sale.status === 'paid') setPendingTipCents(0)\n }, [sale])\n useEffect(() => {\n if (sale?.status === 'paid') displayShowsBasket.current = false\n }, [sale?.status])\n useEffect(() => {\n if (!display.connected || display.asking) return\n if (sale?.payments.some((payment) => payment.status === 'pending' && payment.method === 'card_present')) {\n return\n }\n if (sale?.status === 'paid') return\n if (!mirrored.length && !displayShowsBasket.current) return\n const timer = setTimeout(() => {\n displayShowsBasket.current = mirrored.length > 0\n void display.show(\n mirrored.length\n ? {\n mode: 'cart',\n cart: {\n lines: mirrored.map((line) => ({\n name: line.name,\n ...(line.variantLabel ? { variantLabel: line.variantLabel } : {}),\n quantity: line.quantity,\n amountCents: line.unitAmountCents * line.quantity,\n })),\n itemsCents,\n discountCents,\n taxCents: sale ? Math.max(0, sale.totalCents - estimateCents) : 0,\n totalCents: sale ? sale.totalCents : estimateCents,\n ...(sale\n ? {\n paidCents: sale.paidCents,\n dueCents: sale.dueCents,\n tipCents: posDisplayTipCents(sale, pendingTipCents),\n }\n : {}),\n },\n }\n : { mode: 'idle' },\n )\n }, 400)\n return () => clearTimeout(timer)\n }, [display, mirrored, sale, itemsCents, discountCents, estimateCents, pendingTipCents])\n\n const registersHref = posRegistersSettingsHref(basePath)\n const registerPicker = !planReady ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your plan…'}\n </Typography>\n ) : usableRegisters.length === 0 ? (\n registers.length > 0 ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {'Your registers exceed your plan — remove extras or upgrade in Billing to take payments.'}\n </Typography>\n ) : (\n // A way there, not a path to follow by hand (AGL-3712).\n <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Typography variant=\"body2\" color=\"warning.main\">\n {'No POS register yet. Add one before taking payments.'}\n </Typography>\n {registersHref ? (\n <Button size=\"small\" variant=\"outlined\" href={registersHref}>\n {'Add a register'}\n </Button>\n ) : null}\n </Stack>\n )\n ) : usableRegisters.length > 1 ? (\n <TextField\n label=\"Register\"\n value={registerId}\n onChange={(event) => setRegisterId(event.target.value)}\n size=\"small\"\n select\n disabled={Boolean(sale)}\n >\n {usableRegisters.map((register: any) => (\n <MenuItem key={register.$id} value={register.$id}>\n {register.name}\n </MenuItem>\n ))}\n </TextField>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {usableRegisters[0]?.name}\n </Typography>\n )\n\n /**\n * On a narrow screen the register's bar owns the bottom edge, so it moves\n * the console's floating launchers clear of itself through the shell's\n * `--aglyn-dock-inset-bottom` seam; a launcher left in the corner sat on\n * top of Charge.\n */\n const bottomBarRef = useRef<HTMLDivElement | null>(null)\n useEffect(() => {\n const node = bottomBarRef.current\n if (wide || !node) return undefined\n const root = document.documentElement\n const property = '--aglyn-dock-inset-bottom'\n const publish = () => {\n root.style.setProperty(property, `${Math.round(node.getBoundingClientRect().height) + 20}px`)\n }\n publish()\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(publish)\n observer?.observe(node)\n return () => {\n observer?.disconnect()\n root.style.removeProperty(property)\n }\n }, [wide])\n\n const registerPanel = (\n <Stack spacing={1.5} sx={{ minHeight: 0, flex: 1 }}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"h6\" sx={{ flex: 1 }}>\n {'Register'}\n </Typography>\n {registerId ? (\n <Button\n size=\"small\"\n onClick={() => void pairingFlow.open(registerId, 'display')}\n >\n {display.connected ? 'Display connected' : 'Pair display'}\n </Button>\n ) : null}\n </Stack>\n {registerPicker}\n {(locationDocs?.length ?? 0) > 1 ? (\n <TextField\n label=\"Location\"\n value={locationId}\n onChange={(event) => setLocationId(event.target.value)}\n size=\"small\"\n select\n disabled={Boolean(sale)}\n >\n {(locationDocs ?? []).map((location: any) => (\n <MenuItem key={location.$id} value={location.$id}>\n {location.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {registerId ? (\n <PosOperationsBar\n hostId={hostId}\n registerId={registerId}\n {...(registerName ? { registerName } : {})}\n cashier={cashier}\n onExchange={(returned) =>\n setCustomer(\n returned.email || returned.name\n ? { kind: 'none', id: '', name: returned.name ?? '', email: returned.email, phone: null }\n : null,\n )\n }\n />\n ) : null}\n <PosCartPanel\n lines={sale ? saleLines : lines}\n shortfalls={sale ? [] : shortfalls}\n onQuantity={(index, quantity) =>\n setLines((prev) =>\n quantity <= 0\n ? prev.filter((_line, at) => at !== index)\n : prev.map((line, at) => (at === index ? { ...line, quantity: Math.min(99, quantity) } : line)),\n )\n }\n onRemove={(index) => setLines((prev) => prev.filter((_line, at) => at !== index))}\n onEdit={(index) => {\n const line = lines[index]\n const product = line\n ? (productCache.current.get(line.productId) ?? productsById.get(line.productId))\n : undefined\n if (!line || !product) return\n setItemSheet({\n product,\n editIndex: index,\n initial: {\n ...(line.variantId ? { variantId: line.variantId } : {}),\n ...(line.modifiers ? { modifiers: line.modifiers } : {}),\n quantity: line.quantity,\n },\n })\n }}\n discountPct={discountPct}\n onDiscountPct={setDiscountPct}\n customer={\n sale ? null : (\n <PosCustomerLookup\n hostId={hostId}\n value={customer}\n onChange={setCustomer}\n registerId={registerId}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n />\n )\n }\n locked={Boolean(sale)}\n />\n {sale && user ? (\n sale.status === 'paid' ? (\n <PosReceiptPanel\n user={user}\n hostId={hostId}\n sale={sale}\n context={context}\n display={display}\n onNewSale={resetSale}\n registerId={registerId}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n notify={notify}\n />\n ) : (\n <PosTenderPanel\n user={user}\n hostId={hostId}\n registerId={registerId}\n sale={sale}\n context={context}\n stays={openStays}\n display={display}\n onSale={setSale}\n onVoided={() => {\n setSale(null)\n setSaleLines([])\n }}\n onTipChange={setPendingTipCents}\n {...(cashier.assertion ? { cashierAssertion: cashier.assertion } : {})}\n notify={notify}\n offline={offline.offline}\n {...(offline.ready\n ? {\n onSellOffline: () => {\n // The server's open sale took no payment; it is voided once\n // the connection returns, and the basket rings offline.\n strandedSales.current.push(sale.orderId)\n setSale(null)\n setSaleLines([])\n setOfflineCheckout(true)\n },\n }\n : {})}\n />\n )\n ) : (\n <>\n <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>\n <Typography variant=\"h6\">{'Due'}</Typography>\n <Typography variant=\"h6\">{usd(estimateCents)}</Typography>\n </Box>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Tax is added when you charge.'}\n </Typography>\n <Button\n variant=\"contained\"\n size=\"large\"\n disabled={opening || lines.length === 0 || !registerId}\n onClick={() => void charge()}\n sx={{ minHeight: 56 }}\n >\n {opening\n ? 'Pricing…'\n : offline.offline\n ? `Cash ${usd(offline.totalsFor(lines, discountPct)?.totalCents ?? estimateCents)} (offline)`\n : `Charge ${usd(estimateCents)}`}\n </Button>\n {lastReceipt ? (\n <PosLastReceipt\n hostId={hostId}\n orderId={lastReceipt.orderId}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n />\n ) : null}\n </>\n )}\n </Stack>\n )\n\n return (\n <>\n <NextPageTitle screen={'POS'} />\n <Box\n ref={fill.ref}\n sx={{\n display: 'flex',\n // From under the console's header, nav and page title down to\n // where the page's padding and footer begin, so the whole page fits\n // the window (AGL-3679, AGL-3710).\n height: fill.height,\n overflow: 'hidden',\n }}\n >\n <Box sx={{ flex: 1, p: 2, overflowY: 'auto', pb: wide ? 2 : 12 }}>\n <Box sx={{ mb: 2, '&:empty': { display: 'none' } }}>\n <PosOfflineBanner offline={offline} />\n </Box>\n {/* \"Pay at counter\" orders from this register's kiosks (AGL-3623). */}\n {registerId ? (\n <PosKioskQueue\n user={user}\n hostId={hostId}\n registerId={registerId}\n disabled={Boolean(sale)}\n onTake={(next, nextLines) => {\n setSaleLines(nextLines)\n setSale(next)\n setSheetOpen(true)\n }}\n notify={notify}\n />\n ) : null}\n {/* Orders other channels send to the counter (AGL-3644). */}\n {WidgetSlot ? <PosOrdersZone renderer={WidgetSlot} hostId={hostId} registerId={registerId || null} /> : null}\n <PosProductGrid\n search={search}\n onSearch={setSearch}\n onSearchEnter={() => void handleSearchEnter()}\n scanAdornment={scanAdornment}\n categories={(categoryDocs ?? []).map((category: any) => ({\n $id: category.$id,\n name: String(category.name ?? 'Category'),\n }))}\n categoryId={categoryId}\n onCategory={setCategoryId}\n notices={gridPlan.notices}\n hostId={hostId}\n products={sellProducts}\n basketCounts={basketCounts}\n onTap={(product) => {\n if (sale) return void notify('Finish or void the open sale first', 'info')\n tapProduct(product)\n }}\n />\n </Box>\n {wide ? (\n <Box\n sx={{\n width: { md: 400, lg: 440 },\n borderLeft: 1,\n borderColor: 'divider',\n display: 'flex',\n flexDirection: 'column',\n p: 2,\n overflowY: 'auto',\n }}\n >\n {registerPanel}\n </Box>\n ) : null}\n </Box>\n {!wide ? (\n <>\n <Box\n ref={bottomBarRef}\n sx={{\n position: 'fixed',\n left: 0,\n right: 0,\n bottom: 0,\n p: 1.5,\n bgcolor: 'background.paper',\n borderTop: 1,\n borderColor: 'divider',\n display: 'flex',\n gap: 1,\n alignItems: 'center',\n zIndex: theme.zIndex.appBar,\n }}\n >\n <Badge badgeContent={units} color=\"primary\">\n <Button\n variant=\"outlined\"\n onClick={() => setSheetOpen(true)}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {sale ? 'Payment' : 'Cart'}\n </Button>\n </Badge>\n <Typography variant=\"h6\" sx={{ flex: 1, textAlign: 'right' }}>\n {usd(sale ? sale.dueCents : estimateCents)}\n </Typography>\n {!sale ? (\n <Button\n variant=\"contained\"\n disabled={opening || lines.length === 0 || !registerId}\n onClick={() => void charge()}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Charge'}\n </Button>\n ) : null}\n </Box>\n <Drawer\n anchor=\"bottom\"\n open={sheetOpen}\n onClose={() => setSheetOpen(false)}\n slotProps={{ paper: { sx: { maxHeight: '90dvh', p: 2, borderTopLeftRadius: 16, borderTopRightRadius: 16 } } }}\n >\n {registerPanel}\n </Drawer>\n </>\n ) : null}\n <PosItemDialog\n product={itemSheet?.product ?? null}\n initial={itemSheet?.initial}\n onClose={() => setItemSheet(null)}\n onConfirm={(choice) => {\n const sheet = itemSheet\n setItemSheet(null)\n if (!sheet) return\n if (sheet.editIndex === undefined) {\n addProduct(sheet.product, choice.variant, choice.modifiers, choice.quantity)\n return\n }\n const at = sheet.editIndex\n setLines((prev) =>\n prev.map((line, index) => (index === at ? registerLineFor(sheet.product, choice) : line)),\n )\n }}\n {...(itemSheet?.editIndex !== undefined\n ? {\n onRemove: () => {\n const at = itemSheet.editIndex\n setItemSheet(null)\n setLines((prev) => prev.filter((_line, index) => index !== at))\n },\n }\n : {})}\n />\n <PosOfflineCheckout\n open={offlineCheckout}\n offline={offline}\n hostId={hostId}\n lines={lines}\n discountPct={discountPct}\n customer={customer}\n {...(registerName ? { registerName } : {})}\n {...(cashier.cashier ? { cashierName: cashier.cashier.name } : {})}\n onClose={() => setOfflineCheckout(false)}\n onRung={() => undefined}\n onDone={() => {\n setOfflineCheckout(false)\n setLines([])\n setDiscountPct(0)\n setCustomer(null)\n setSheetOpen(false)\n }}\n />\n {pairingFlow.dialog}\n </>\n )\n}\nPosConsolePage.displayName = 'PosConsolePage'\n\nexport default PosConsolePage\n"],"names":["Aglyn","CommerceModel","PRODUCT_LIST_BASE","PRODUCT_LIST_QUERY","NextPageTitle","useSnackbar","planListQuery","useViewportFill","nameSearchNormalizers","Badge","Box","Button","Drawer","MenuItem","Stack","TextField","Typography","useMediaQuery","useTheme","collection","getDocs","limit","query","where","memo","useCallback","useEffect","useMemo","useRef","useState","useFirestore","useUser","useFirestoreCollection","listQueryConstraints","useOrgPlan","newAttemptKey","openPosSale","posRegisterContext","posTender","PosRequestError","usd","PosCartPanel","ScanAdornment","useScannerWedge","PosCustomerLookup","PosLastReceipt","PosOperationsBar","usePosCashier","usePosOpsSettings","POS_QUICK_KEYS","POS_TOUCH_PX","PosProductGrid","PosItemDialog","posItemNeedsChoice","PosReceiptPanel","PosTenderPanel","PosKioskQueue","posDisplayTipCents","usePosDisplay","posRegistersSettingsHref","usePosPairing","useConsoleWidgetSlot","POS_ORDERS_ZONE","PosOfflineBanner","PosOfflineCheckout","usePosOffline","SELLABLE","field","op","value","POS_GRID_CEILING","posProductPlan","options","typed","search","trim","plan","POS_GRID_QUERY","base","clauses","code","categoryId","quickKeys","filters","path","fields","column","kind","tokensPath","operators","POS_CATEGORY_KEY","registerLineFor","product","choice","variant","modifiers","quantity","resolved","resolveLineModifiers","picked","ok","label","lineLabelWithModifiers","Object","keys","length","values","join","undefined","productId","$id","id","variantId","name","variantLabel","unitAmountCents","Math","round","Number","priceUsd","extraCents","lineKey","line","modifierSelectionKey","PosOrdersZone","props","renderer","Renderer","hostId","registerId","slot","orgId","PosConsolePage","basePath","liveRegister","usableRegisters","offline","WidgetSlot","firestore","data","user","enqueueSnackbar","theme","wide","breakpoints","up","setSearch","setCategoryIdState","window","localStorage","getItem","setCategoryId","setItem","gridPlan","productDocs","idField","categoryDocs","locationDocs","registerDocs","org","ready","planReady","registers","sort","a","b","String","localeCompare","registerCap","checkHostRegisterQuota","withinCap","registersWithinCap","filter","r","has","reservationDocs","openStays","lines","setLines","discountPct","setDiscountPct","customer","setCustomer","customerEmail","email","locationId","setLocationId","setRegisterId","first","registerName","find","register","opsSettings","cashier","autoLockMinutes","lastReceipt","setLastReceipt","context","setContext","userRef","current","uid","signedIn","active","then","answer","settings","terminal","catch","sale","setSale","saleLines","setSaleLines","opening","setOpening","sheetOpen","setSheetOpen","display","attemptKey","fill","min","products","map","liftLegacyProduct","loadCatalog","docs","snapshot","openShiftId","assertion","cashierAssertion","liveProducts","offlineCheckout","setOfflineCheckout","strandedSales","orderIds","splice","orderId","sellProducts","gridProducts","productsById","Map","shortfalls","get","stockShortfall","variants","itemsCents","reduce","sum","discountCents","estimateCents","units","notify","message","persist","allowDuplicate","onPairingError","pairingFlow","onError","addProduct","next","prev","existing","itemSheet","setItemSheet","productCache","tapProduct","set","productModifierGroups","initial","basketCounts","counts","lookupCode","scanned","needle","toLowerCase","found","findByCode","lookup","hit","error","console","reportNetworkFailure","item","barcode","sku","handleSearchEnter","scanAdornment","onScan","chargeInFlight","charge","unavailableReason","opened","status","totalCents","totals","paidCents","dueCents","tenderableCents","tipCents","payments","resetSale","mirrored","displayShowsBasket","pendingTipCents","setPendingTipCents","connected","asking","some","payment","method","timer","setTimeout","show","mode","cart","amountCents","taxCents","max","clearTimeout","registersHref","registerPicker","color","spacing","sx","alignItems","size","href","onChange","event","target","select","disabled","Boolean","bottomBarRef","node","root","document","documentElement","property","publish","style","setProperty","getBoundingClientRect","height","observer","ResizeObserver","observe","disconnect","removeProperty","registerPanel","minHeight","flex","direction","onClick","open","location","onExchange","returned","phone","onQuantity","index","_line","at","onRemove","onEdit","editIndex","onDiscountPct","locked","onNewSale","cashierName","stays","onSale","onVoided","onTipChange","onSellOffline","push","justifyContent","totalsFor","screen","ref","overflow","p","overflowY","pb","mb","onTake","nextLines","onSearch","onSearchEnter","categories","category","onCategory","notices","onTap","width","md","lg","borderLeft","borderColor","flexDirection","position","left","right","bottom","bgcolor","borderTop","gap","zIndex","appBar","badgeContent","textAlign","anchor","onClose","slotProps","paper","maxHeight","borderTopLeftRadius","borderTopRightRadius","onConfirm","sheet","onRung","onDone","dialog","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AAErC,YAAYC,mBAAmB,uBAAa;AAC5C,SACEC,iBAAiB,EACjBC,kBAAkB,QACb,wCAAoC;AAC3C,SAASC,aAAa,QAAQ,0DAAyD;AACvF,SAASC,WAAW,QAAQ,8BAA6B;AAEzD,SAASC,aAAa,QAAQ,6CAA4C;AAC1E,SAASC,eAAe,QAAQ,+CAA8C;AAC9E,SAASC,qBAAqB,QAAQ,qCAAoC;AAC1E,SACEC,KAAK,EACLC,GAAG,EACHC,MAAM,EACNC,MAAM,EACNC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,UAAU,EACVC,aAAa,EACbC,QAAQ,QACH,gBAAe;AACtB,SACEC,UAAU,EACVC,OAAO,EACPC,KAAK,EACLC,KAAK,EACLC,KAAK,QACA,qBAAoB;AAC3B,SAASC,IAAI,EAAEC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAC/E,SAASC,YAAY,EAAEC,OAAO,QAAQ,iCAAgC;AACtE,SAASC,sBAAsB,QAAQ,iCAAgC;AACvE,SAASC,oBAAoB,QAAQ,sDAAqD;AAC1F,SAASC,UAAU,QAAQ,iCAAgC;AAC3D,SACEC,aAAa,EACbC,WAAW,EACXC,kBAAkB,EAClBC,SAAS,EACTC,eAAe,EACfC,GAAG,QAGE,mBAAe;AACtB,SAASC,YAAY,QAA2B,oCAAgC;AAChF,SAASC,aAAa,QAAQ,yCAAqC;AACnE,SAASC,eAAe,QAAQ,iCAA6B;AAC7D,SACEC,iBAAiB,EACjBC,cAAc,EACdC,gBAAgB,EAChBC,aAAa,EACbC,iBAAiB,QAEZ,4BAAwB;AAC/B,SAASC,cAAc,EAAEC,YAAY,EAAEC,cAAc,QAAQ,sCAAkC;AAC/F,SAASC,aAAa,EAAEC,kBAAkB,QAA4B,qCAAiC;AACvG,SAASC,eAAe,QAAQ,uCAAmC;AACnE,SAASC,cAAc,QAAQ,sCAAkC;AACjE,SAASC,aAAa,QAAQ,qCAAiC;AAC/D,SAASC,kBAAkB,EAAEC,aAAa,QAAQ,2BAAuB;AACzE,SAASC,wBAAwB,EAAEC,aAAa,QAAQ,iCAA6B;AACrF,SAEEC,oBAAoB,QACf,qDAAoD;AAC3D,SAASC,eAAe,QAAQ,iBAAa;AAC7C,SAASC,gBAAgB,EAAEC,kBAAkB,EAAEC,aAAa,QAAQ,oCAAgC;AAEpG,4EAA4E,GAC5E,MAAMC,WAA8B;IAAEC,OAAO;IAAUC,IAAI;IAAUC,OAAO;AAAS;AAErF;;;CAGC,GACD,MAAMC,mBAAmB;AAEzB;;;;;;CAMC,GACD,OAAO,SAASC,eAAeC,OAO9B;QACeA;IAAd,MAAMC,SAAQD,kBAAAA,QAAQE,MAAM,qBAAdF,gBAAgBG,IAAI;IAClC,MAAMC,OAAOtE,cACXuE,gBACA;QACEC,MAAM5E;QACN6E,SAAS;YACPb;eACIM,QAAQQ,IAAI,GACZ;gBAAC;oBAAEb,OAAOK,QAAQQ,IAAI,CAACb,KAAK;oBAAEC,IAAI;oBAAYC,OAAOG,QAAQQ,IAAI,CAACX,KAAK;gBAAC;aAAE,GAC1E,EAAE;eACFG,QAAQS,UAAU,GAClB;gBAAC;oBAAEd,OAAO;oBAAeC,IAAI;oBAAYC,OAAOG,QAAQS,UAAU;gBAAC;aAAE,GACrE,EAAE;SACP;QACD,sEAAsE;QACtE,gEAAgE;QAChEP,QAAQD,SAAS,CAACD,QAAQS,UAAU,GAAG;YAACR;SAAM,GAAG,EAAE;IACrD,GACAjE;IAEF,wEAAwE;IACxE,uEAAuE;IACvE,0EAA0E;IAC1E,qEAAqE;IACrE,oDAAoD;IACpD,IAAIgE,QAAQU,SAAS,IAAI,CAACT,SAAS,CAACD,QAAQQ,IAAI,EAAE;QAChD,OAAO,aACFJ;YACHO,SAAS;mBAAIP,KAAKO,OAAO;gBAAE;oBAAEC,MAAM;oBAAehB,IAAI;oBAAMC,OAAO;gBAAK;aAAE;;IAE9E;IACA,OAAOO;AACT;AAEA;;;;CAIC,GACD,OAAO,MAAMC,iBAAiB,aACzB1E;IACHkF,QAAQ;WACHlF,mBAAmBkF,MAAM;QAC5B;YACEC,QAAQ;YACRC,MAAM;YACNH,MAAM;YACNI,YAAY;YACZC,WAAW;gBAAC;aAAW;QACzB;KACD;GAC2B;AAE9B;;;;;;;;;;CAUC,GACD;;;;;;;;;;;CAWC,GACD,wEAAwE,GACxE,MAAMC,mBAAmB;AAEzB,qFAAqF,GACrF,OAAO,SAASC,gBACdC,OAAY,EACZC,MAAqB;QAMPC,kBACMA;IALpB,MAAM,EAAEA,OAAO,EAAEC,SAAS,EAAEC,QAAQ,EAAE,GAAGH;IACzC,MAAMI,WAAWhG,cAAciG,oBAAoB,CAACN,SAASG;IAC7D,MAAMI,SAASF,SAASG,EAAE,GAAGH,SAASF,SAAS,GAAG,EAAE;IACpD,MAAMM,QAAQpG,cAAcqG,sBAAsB,CAChDC,OAAOC,IAAI,EAACV,mBAAAA,QAAQtB,OAAO,YAAfsB,mBAAmB,CAAC,GAAGW,MAAM,GACrCF,OAAOG,MAAM,EAACZ,oBAAAA,QAAQtB,OAAO,YAAfsB,oBAAmB,CAAC,GAAGa,IAAI,CAAC,SAC1CC,WACJT;IAEF,OAAO;QACLU,WAAWjB,QAAQkB,GAAG;OAClBhB,QAAQiB,EAAE,KAAK,YAAY;QAAEC,WAAWlB,QAAQiB,EAAE;IAAC,IAAI,CAAC;QAC5DE,MAAMrB,QAAQqB,IAAI;OACdZ,QAAQ;QAAEa,cAAcb;IAAM,IAAI,CAAC;QACvCc,iBACEC,KAAKC,KAAK,CAACC,OAAOxB,QAAQyB,QAAQ,IAAI,OAAQtB,CAAAA,SAASG,EAAE,GAAGH,SAASuB,UAAU,GAAG,CAAA;QACpFxB;OACID,UAAUU,MAAM,GAAG;QAAEV;IAAU,IAAI,CAAC;AAE5C;AAEA,sEAAsE,GACtE,SAAS0B,QAAQC,IAAiE;QACpDA;IAA5B,OAAO,GAAGA,KAAKb,SAAS,CAAC,CAAC,GAAEa,kBAAAA,KAAKV,SAAS,YAAdU,kBAAkB,GAAG,CAAC,EAAEzH,cAAc0H,oBAAoB,CAACD,KAAK3B,SAAS,GAAG;AAC1G;AAEA;;;;CAIC,GACD,MAAM6B,8BAAgBpG,KAAK,SAASoG,cAAcC,KAIjD;IACC,MAAM,EAAEC,UAAUC,QAAQ,EAAEC,MAAM,EAAEC,UAAU,EAAE,GAAGJ;IACnD,qBAAO,KAACE;QAASG,MAAMpE,gBAAgBiD,EAAE;QAAEiB,QAAQA;QAAQG,OAAOvB;QAAWqB,YAAYA;;AAC3F;AAEA,OAAO,SAASG,eAAe,EAAEJ,MAAM,EAAEK,QAAQ,EAA0B;4BA0L1CC;QApF7BC,uBA2ZGA,mBAsLuBC;IAtrB5B,MAAMC,aAAa5E;IACnB,MAAM6E,YAAY5G;IAClB,MAAM,EAAE6G,MAAMC,IAAI,EAAE,GAAG7G;IACvB,MAAM,EAAE8G,eAAe,EAAE,GAAGxI;IAC5B,MAAMyI,QAAQ5H;IACd,MAAM6H,OAAO9H,cAAc6H,MAAME,WAAW,CAACC,EAAE,CAAC;IAEhD,MAAM,CAACvE,QAAQwE,UAAU,GAAGrH,SAAS;IACrC,wEAAwE;IACxE,6CAA6C;IAC7C,MAAM,CAACoD,YAAYkE,mBAAmB,GAAGtH,SAAS;QAChD,IAAI;gBACKuH;YAAP,QAAOA,+BAAAA,OAAOC,YAAY,CAACC,OAAO,CAAC5D,6BAA5B0D,+BAAiD;QAC1D,EAAE,eAAM;YACN,OAAO;QACT;IACF;IACA,MAAMG,gBAAgB9H,YAAY,CAACsF;QACjCoC,mBAAmBpC;QACnB,IAAI;YACFqC,OAAOC,YAAY,CAACG,OAAO,CAAC9D,kBAAkBqB;QAChD,EAAE,eAAM;QACN,wDAAwD;QAC1D;IACF,GAAG,EAAE;IACL,MAAM0C,WAAW9H,QACf,IACEsD,eAAehC,iBACXsB,eAAe;YAAEG;YAAQQ,WAAW;QAAK,KACzCX,eAAe;YAAEG;YAAQO;QAAW,IAC1C;QAACP;QAAQO;KAAW;IAEtB,MAAM,EAAE0D,MAAMe,WAAW,EAAE,GAAG1H,uBAC5B;;;;;KAKC,GACD,IACEV,MACEH,WAAWuH,WAAW,SAASV,QAAQ,gBACpC/F,qBAAqBwH,WACxBpI,MAAMiD,oBAEV;QAACoE;QAAWV;QAAQyB;KAAS,EAC7B;QAAEE,SAAS;IAAM;IAEnB,MAAM,EAAEhB,MAAMiB,YAAY,EAAE,GAAG5H,uBAC7B,IAAMV,MAAMH,WAAWuH,WAAW,SAASV,QAAQ,sBAAsB3G,MAAM,MAC/E;QAACqH;QAAWV;KAAO,EACnB;QAAE2B,SAAS;IAAM;IAEnB,MAAM,EAAEhB,MAAMkB,YAAY,EAAE,GAAG7H,uBAC7B,IAAMV,MAAMH,WAAWuH,WAAW,SAASV,QAAQ,cAAc3G,MAAM,MACvE;QAACqH;QAAWV;KAAO,EACnB;QAAE2B,SAAS;IAAM;IAEnB,MAAM,EAAEhB,MAAMmB,YAAY,EAAE,GAAG9H,uBAC7B,IAAMV,MAAMH,WAAWuH,WAAW,SAASV,QAAQ,cAAc3G,MAAM,MACvE;QAACqH;QAAWV;KAAO,EACnB;QAAE2B,SAAS;IAAM;IAEnB,MAAM,EAAEI,GAAG,EAAEC,OAAOC,SAAS,EAAE,GAAG/H,WAAW8F;IAC7C,MAAMkC,YAAY;WAAKJ,uBAAAA,eAAgB,EAAE;KAAE,CAACK,IAAI,CAAC,CAACC,GAAQC;YACjDD,SAAmCC;eAA1CC,QAAOF,UAAAA,EAAEnD,IAAI,YAANmD,UAAU,IAAIG,aAAa,CAACD,QAAOD,UAAAA,EAAEpD,IAAI,YAANoD,UAAU;;IAEtD,2EAA2E;IAC3E,2DAA2D;IAC3D,MAAMG,cAAcxK,MAAMyK,sBAAsB,CAACV,KAAK/B,QAAQkC,UAAUzD,MAAM,EAAEpF,KAAK;IACrF,MAAMqJ,YAAYzK,cAAc0K,kBAAkB,CAACT,WAAWM;IAC9D,MAAMjC,kBAAkB0B,YAAYC,UAAUU,MAAM,CAAC,CAACC,IAAWH,UAAUI,GAAG,CAACD,EAAE/D,GAAG,KAAK,EAAE;IAC3F;;GAEC,GACD,MAAM,EAAE6B,MAAMoC,eAAe,EAAE,GAAG/I,uBAChC,IACEV,MACEH,WAAWuH,WAAW,SAASV,QAAQ,iBACvCzG,MAAM,UAAU,MAAM,eACtBF,MAAM,OAEV;QAACqH;QAAWV;KAAO,EACnB;QAAE2B,SAAS;IAAM;IAEnB,MAAMqB,YAAYD,0BAAAA,kBAAmB,EAAE;IAEvC,MAAM,CAACE,OAAOC,SAAS,GAAGrJ,SAAyB,EAAE;IACrD,MAAM,CAACsJ,aAAaC,eAAe,GAAGvJ,SAAS;IAC/C,0EAA0E;IAC1E,MAAM,CAACwJ,UAAUC,YAAY,GAAGzJ,SAAqC;IACrE,MAAM0J,wBAAgBF,4BAAAA,SAAUG,KAAK,mBAAI;IACzC,MAAM,CAACC,YAAYC,cAAc,GAAG7J,SAAS;IAC7C,MAAM,CAACoG,YAAY0D,cAAc,GAAG9J,SAAS;IAC7CH,UAAU;QACR,IAAIuG,cAAcM,gBAAgB9B,MAAM,KAAK,GAAG;QAChD,MAAMmF,QAAQrD,eAAe,CAAC,EAAE;QAChCoD,cAAcC,MAAM9E,GAAG;QACvB,IAAI8E,MAAMH,UAAU,EAAEC,cAAcE,MAAMH,UAAU;IACtD,GAAG;QAAClD;QAAiBN;KAAW;IAChC,MAAM4D,eAAevB,iBACnB/B,wBAAAA,gBAAgBuD,IAAI,CAAC,CAACC,WAAkBA,SAASjF,GAAG,KAAKmB,gCAAzDM,sBAAsEtB,IAAI,oBAAI;IAEhF,wEAAwE;IACxE,MAAM+E,cAAchJ,kBAAkBgF;IACtC,MAAMiE,UAAUlJ,cAAc;QAC5BiF;QACAC;QACAiE,iBAAiBF,YAAYE,eAAe;IAC9C;IACA,0EAA0E;IAC1E,MAAM,CAACC,aAAaC,eAAe,GAAGvK,SAAqC;IAE3E,MAAM,CAACwK,SAASC,WAAW,GAAGzK,SAAoC;IAClE,wEAAwE;IACxE,0EAA0E;IAC1E,0CAA0C;IAC1C,MAAM0K,UAAU3K,OAAOgH;IACvB2D,QAAQC,OAAO,GAAG5D;IAClB,MAAM6D,eAAM7D,wBAAAA,KAAM6D,GAAG,oBAAI;IACzB/K,UAAU;QACR,MAAMgL,WAAWH,QAAQC,OAAO;QAChC,IAAI,CAACE,UAAU;QACf,IAAIC,SAAS;QACbtK,mBAAmBqK,UAAU1E,QAC1B4E,IAAI,CAAC,CAACC;YACL,oEAAoE;YACpE,qCAAqC;YACrC,IAAIF,WAAUE,0BAAAA,OAAQC,QAAQ,MAAID,0BAAAA,OAAQE,QAAQ,GAAET,WAAWO;QACjE,GACCG,KAAK,CAAC,IAAMpG;QACf,OAAO;YACL+F,SAAS;QACX;IACF,GAAG;QAACF;QAAKzE;KAAO;IAEhB,wEAAwE,GACxE,MAAM,CAACiF,MAAMC,QAAQ,GAAGrL,SAAgC;IACxD,MAAM,CAACsL,WAAWC,aAAa,GAAGvL,SAAyB,EAAE;IAC7D,MAAM,CAACwL,SAASC,WAAW,GAAGzL,SAAS;IACvC,MAAM,CAAC0L,WAAWC,aAAa,GAAG3L,SAAS;IAC3C,MAAM4L,UAAU/J,cAAckF,MAAMZ,QAAQC;IAE5C;;;;GAIC,GACD,MAAMyF,aAAa9L,OAAO;IAC1B,MAAM+L,OAAOpN,gBAAgB;QAAEqN,KAAK;IAAI;IACxClM,UAAU;QACRgM,WAAWlB,OAAO,GAAG;IACvB,GAAG;QAACvB;QAAOE;KAAY;IAEvB,MAAM0C,WAAWlM,QACf,IACE;eAAK+H,sBAAAA,cAAe,EAAE;SAAE,CAACoE,GAAG,CAAC,CAAClI,UAAkB,aAC3C3F,cAAc8N,iBAAiB,CAACnI;gBACnCkB,KAAKlB,QAAQkB,GAAG;iBAEpB;QAAC4C;KAAY;IAEf;;;;GAIC,GACD,MAAMsE,cAAcvM,YAClB,UACE,AACE,CAAA,MAAML,QACJE,MACEH,WAAWuH,WAAW,SAASV,QAAQ,gBACpC/F,qBAAqBsC,eAAe,CAAC,KACxClD,MAAMiD,mBAEV,EACA2J,IAAI,CAACH,GAAG,CAAC,CAACI,WAAc,aAAMA,SAASvF,IAAI;gBAAgC7B,KAAKoH,SAASnH,EAAE;iBAC/F;QAAC2B;QAAWV;KAAO;IAErB,MAAMM,eAAeC,gBAAgBuD,IAAI,CAAC,CAACC,WAAkBA,SAASjF,GAAG,KAAKmB;IAC9E,MAAMO,UAAUvE,cAAc;QAC5B+D;QACAY;QACAX;QACAkG,aAAa7F,gBAAgBA,4BAAAA,aAAa6F,WAAW,YAAxB7F,4BAA4B,OAAQ1B;QACjE6E;OACIQ,QAAQmC,SAAS,GAAG;QAAEC,kBAAkBpC,QAAQmC,SAAS;IAAC,IAAI,CAAC;QACnEE,cAAcT;QACdG;;IAEF,MAAM,CAACO,iBAAiBC,mBAAmB,GAAG3M,SAAS;IACvD,gFAAgF,GAChF,MAAM4M,gBAAgB7M,OAAiB,EAAE;IACzCF,UAAU;QACR,IAAI8G,QAAQA,OAAO,IAAI,CAACI,QAAQ,CAAC6F,cAAcjC,OAAO,CAAC/F,MAAM,EAAE;QAC/D,MAAMiI,WAAWD,cAAcjC,OAAO,CAACmC,MAAM,CAAC;QAC9C,KAAK,MAAMC,WAAWF,SAAU;YAC9B,KAAKpM,UAAUsG,MAAMZ,QAAQ4G,SAAS,QAAQ5B,KAAK,CAAC,IAAMpG;QAC5D;IACF,GAAG;QAAC4B,QAAQA,OAAO;QAAEI;QAAMZ;KAAO;IAClC,MAAM6G,eAAelN,QACnB,IAAO6G,QAAQA,OAAO,IAAIA,QAAQwB,KAAK,GAAGxB,QAAQsG,YAAY,CAACpK,QAAQO,YAAYhC,kBAAkB4K,UACrG;QAACrF;QAAS9D;QAAQO;QAAY4I;KAAS;IAEzC,MAAMkB,eAAepN,QACnB,IAAM,IAAIqN,IAAiBH,aAAaf,GAAG,CAAC,CAAClI,UAAiB;gBAACA,QAAQkB,GAAG;gBAAElB;aAAQ,IACpF;QAACiJ;KAAa;IAEhB,mCAAmC,GACnC,MAAMI,aAAatN,QACjB,IACEsJ,MAAM6C,GAAG,CAAC,CAACpG;gBAKPA;gBAAkB9B,oBAAAA;YAJpB,MAAMA,UAAemJ,aAAaG,GAAG,CAACxH,KAAKb,SAAS;YACpD,IAAI,CAACjB,SAAS,OAAO;YACrB,OAAO3F,cAAckP,cAAc,CACjCvJ,UACA8B,kBAAAA,KAAKV,SAAS,YAAdU,mBAAkB9B,oBAAAA,QAAQwJ,QAAQ,sBAAhBxJ,qBAAAA,iBAAkB,CAAC,EAAE,qBAArBA,mBAAuBmB,EAAE,EAC3CW,KAAK1B,QAAQ;QAEjB,IACF;QAACiF;QAAO8D;KAAa;IAGvB,MAAMM,aAAapE,MAAMqE,MAAM,CAAC,CAACC,KAAK7H,OAAS6H,MAAM7H,KAAKP,eAAe,GAAGO,KAAK1B,QAAQ,EAAE;IAC3F,MAAMwJ,gBAAgBpI,KAAKC,KAAK,CAAC,AAACgI,aAAalE,cAAe;IAC9D,MAAMsE,gBAAgBJ,aAAaG;IACnC,MAAME,QAAQzE,MAAMqE,MAAM,CAAC,CAACC,KAAK7H,OAAS6H,MAAM7H,KAAK1B,QAAQ,EAAE;IAE/D,MAAM2J,SAASlO,YACb,CAACmO,SAAiB9J;QAChB+C,gBAAgB+G,SAAS;YAAE9J;YAAS+J,SAAS;YAAOC,gBAAgB;QAAK;IAC3E,GACA;QAACjH;KAAgB;IAGnB;;;GAGC,GACD,MAAMkH,iBAAiBtO,YAAY,CAACmO,UAAoBD,OAAOC,SAAS,UAAU;QAACD;KAAO;IAC1F,MAAMK,cAAcpM,cAAc;QAAEgF;QAAMZ;QAAQiI,SAASF;IAAe;IAE1E;;;;GAIC,GACD,MAAMG,aAAazO,YACjB,CAACmE,SAAcE,SAAeC,YAA+C,EAAE,EAAEC,WAAW,CAAC;QAC3F,MAAMmK,OAAOxK,gBAAgBC,SAAS;YACpCE,OAAO,EAAEA,kBAAAA,UAAWF,QAAQwJ,QAAQ,CAAC,EAAE;YACvCrJ;YACAC;QACF;QACAkF,SAAS,CAACkF;YACR,MAAMC,WAAWD,KAAKtE,IAAI,CAAC,CAACpE,OAASD,QAAQC,UAAUD,QAAQ0I;YAC/D,IAAIE,UAAU;gBACZ,OAAOD,KAAKtC,GAAG,CAAC,CAACpG,OACfA,SAAS2I,WACL,aAAK3I;wBAAM1B,UAAUoB,KAAKwG,GAAG,CAAC,IAAIlG,KAAK1B,QAAQ,GAAGmK,KAAKnK,QAAQ;yBAC/D0B;YAER;YACA,OAAO;mBAAI0I;gBAAMD;aAAK;QACxB;IACF,GACA,EAAE;IAGJ,kEAAkE,GAClE,MAAM,CAACG,WAAWC,aAAa,GAAG1O,SAIxB;IACV,uEAAuE;IACvE,mDAAmD;IACnD,MAAM2O,eAAe5O,OAAO,IAAIoN;IAChC,MAAMyB,aAAahP,YACjB,CAACmE,SAAcE;QACb0K,aAAahE,OAAO,CAACkE,GAAG,CAAC9K,QAAQkB,GAAG,EAAElB;QACtC,IAAIvC,mBAAmBuC,YAAY,CAAEE,CAAAA,WAAW7F,cAAc0Q,qBAAqB,CAAC/K,SAASa,MAAM,KAAK,CAAA,GAAI;YAC1G8J,aAAa;gBACX3K;eACIE,UAAU;gBAAE8K,SAAS;oBAAE5J,WAAWlB,QAAQiB,EAAE;oBAAEf,UAAU;gBAAE;YAAE,IAAI,CAAC;YAEvE;QACF;QACAkK,WAAWtK,SAASE;IACtB,GACA;QAACoK;KAAW;IAEd,MAAMW,eAAelP,QAAQ;YAE2BmP;QADtD,MAAMA,SAAS,IAAI9B;QACnB,KAAK,MAAMtH,QAAQuD,MAAO6F,OAAOJ,GAAG,CAAChJ,KAAKb,SAAS,EAAE,EAACiK,cAAAA,OAAO5B,GAAG,CAACxH,KAAKb,SAAS,aAAzBiK,cAA8B,KAAKpJ,KAAK1B,QAAQ;QACtG,OAAO8K;IACT,GAAG;QAAC7F;KAAM;IAEV;;;GAGC,GACD,MAAM8F,aAAatP,YAAY,OAAOuP;YA+BlCpL;QA9BF,MAAMqL,SAASD,QAAQrM,IAAI,GAAGuM,WAAW;QACzC,IAAI,CAACD,UAAUhE,MAAM;QACrB,IAAIzE,QAAQA,OAAO,EAAE;YACnB,MAAM2I,QAAQ3I,QAAQ4I,UAAU,CAACH;YACjC,IAAI,CAACE,OAAO,OAAO,KAAKxB,OAAO,CAAC,oBAAoB,EAAEqB,QAAQrM,IAAI,GAAG,CAAC,CAAC,EAAE;YACzE8L,WAAWU,MAAMvL,OAAO,EAAEuL,MAAMrL,OAAO;YACvCoD,UAAU;YACV;QACF;QACA,MAAMmI,SAAS,OAAOlN;YACpB,MAAMgN,QAAQ,MAAM/P,QAClBE,MACEH,WAAWuH,WAAW,SAASV,QAAQ,gBACpC/F,qBAAqBsC,eAAe;gBAAES,MAAM;oBAAEb;oBAAOE,OAAO4M;gBAAO;YAAE,KACxE5P,MAAM;YAGV,OAAO8P,MAAMlD,IAAI,CAAC,EAAE;QACtB;QACA,IAAIqD;QACJ,IAAI;gBACK;YAAPA,OAAO,OAAA,MAAMD,OAAO,uBAAb,OAA8B,MAAMA,OAAO;QACpD,EAAE,OAAOE,OAAO;YACdC,QAAQD,KAAK,CAACA;YACd/I,QAAQiJ,oBAAoB;YAC5B,OAAO,KAAK9B,OAAO,2CAA2C;QAChE;QACA,IAAI,CAAC2B,KAAK,OAAO,KAAK3B,OAAO,CAAC,oBAAoB,EAAEqB,QAAQrM,IAAI,GAAG,CAAC,CAAC,EAAE;QACvE,MAAMiB,UAAU,aAAK3F,cAAc8N,iBAAiB,CAACuD,IAAI3I,IAAI;YAAY7B,KAAKwK,IAAIvK,EAAE;;QACpF,MAAMjB,WACJF,yBAAAA,QAAQwJ,QAAQ,CAACtD,IAAI,CACnB,CAAC4F;gBACCA,eAAiDA;mBAAjDA,EAAAA,gBAAAA,KAAKC,OAAO,qBAAZD,cAAc/M,IAAI,GAAGuM,WAAW,QAAOD,UAAUS,EAAAA,YAAAA,KAAKE,GAAG,qBAARF,UAAU/M,IAAI,GAAGuM,WAAW,QAAOD;sBAFxFrL,yBAGKA,QAAQwJ,QAAQ,CAAC,EAAE;QAC1B,wEAAwE;QACxE,8CAA8C;QAC9CqB,WAAW7K,SAASE;QACpBoD,UAAU;IACZ,GAAG;QAAC+D;QAAMvE;QAAWV;QAAQyI;QAAYd;QAAQnH;KAAQ;IACzD,MAAMqJ,oBAAoBpQ,YAAY,IAAMsP,WAAWrM,SAAS;QAACqM;QAAYrM;KAAO;IACpF,0EAA0E;IAC1E,yEAAyE;IACzE/B,gBAAgB,CAACqC,OAAS,KAAK+L,WAAW/L,OAAO,CAACiI,QAAQ,CAACqD;IAC3D,MAAMwB,gBAAgBnQ,QACpB,kBAAM,KAACe;YAAc2D,OAAM;YAAiC0L,QAAQ,CAAC/M,OAAS,KAAK+L,WAAW/L;YAC9F;QAAC+L;KAAW;IAGd,oEAAoE,GACpE,sEAAsE;IACtE,wEAAwE;IACxE,yBAAyB;IACzB,MAAMiB,iBAAiBpQ,OAAO;IAC9B,MAAMqQ,SAASxQ,YAAY;QACzB,IAAIuQ,eAAexF,OAAO,IAAIvB,MAAMxE,MAAM,KAAK,KAAK,CAACmC,MAAM;QAC3D,IAAI,CAACX,YAAY,OAAO,KAAK0H,OAAO,2CAA2C;QAC/E,6EAA6E;QAC7E,IAAInH,QAAQA,OAAO,EAAE;gBACoBA;YAAvC,IAAI,CAACA,QAAQwB,KAAK,EAAE,OAAO,KAAK2F,QAAOnH,6BAAAA,QAAQ0J,iBAAiB,YAAzB1J,6BAA6B,kCAAkC;YACtGgG,mBAAmB;YACnB;QACF;QACA,IAAI,CAACd,WAAWlB,OAAO,EAAEkB,WAAWlB,OAAO,GAAGrK;QAC9C6P,eAAexF,OAAO,GAAG;QACzBc,WAAW;QACX,IAAI;YACF,MAAM6E,SAAS,MAAM/P,YAAYwG,MAAM8E,WAAWlB,OAAO,EAAE;gBACzDxE;gBACAC;gBACAgD;gBACAE;eACII,gBAAgB;gBAAEA;YAAc,IAAI,CAAC,GACrCF,WAAW;gBAAEA;YAAS,IAAI,CAAC,GAC3BY,QAAQmC,SAAS,GAAG;gBAAEC,kBAAkBpC,QAAQmC,SAAS;YAAC,IAAI,CAAC,GAC/D3C,aAAa;gBAAEA;YAAW,IAAI,CAAC;YAErC2B,aAAanC;YACbiC,QAAQ;gBACN0B,SAASuD,OAAOvD,OAAO;gBACvBwD,QAAQ;gBACRC,YAAYF,OAAOG,MAAM,CAACD,UAAU;gBACpCE,WAAW;gBACXC,UAAUL,OAAOG,MAAM,CAACD,UAAU;gBAClCI,iBAAiBN,OAAOG,MAAM,CAACD,UAAU;gBACzCK,UAAU;gBACVC,UAAU,EAAE;YACd;YACAnF,aAAa;QACf,EAAE,OAAO+D,OAAO;YACd,IAAIA,iBAAiBhP,iBAAiB;gBACpCoN,OAAO4B,MAAM3B,OAAO,EAAE;YACxB,OAAO;gBACL,iEAAiE;gBACjEpH,QAAQiJ,oBAAoB;gBAC5B9B,OAAO,wEAAwE;YACjF;QACF,SAAU;YACRqC,eAAexF,OAAO,GAAG;YACzBc,WAAW;QACb;IACF,GAAG;QAACrC;QAAOrC;QAAMX;QAAYD;QAAQmD;QAAaI;QAAeF;QAAUY,QAAQmC,SAAS;QAAE3C;QAAYkE;QAAQnH;KAAQ;IAE1H,MAAMoK,YAAYnR,YAAY;QAC5B,IAAIwL,CAAAA,wBAAAA,KAAMmF,MAAM,MAAK,QAAQhG,eAAe;YAAEwC,SAAS3B,KAAK2B,OAAO;QAAC;QACpE1B,QAAQ;QACRE,aAAa,EAAE;QACflC,SAAS,EAAE;QACXE,eAAe;QACfE,YAAY;QACZkC,aAAa;IACf,GAAG;QAACP;KAAK;IAET,uEAAuE;IACvE,MAAM4F,WAAW5F,OAAOE,YAAYlC;IACpC,4EAA4E;IAC5E,wEAAwE;IACxE,qEAAqE;IACrE,2EAA2E;IAC3E,8BAA8B;IAC9B,MAAM6H,qBAAqBlR,OAAO;IAClC,2EAA2E;IAC3E,qDAAqD;IACrD,MAAM,CAACmR,iBAAiBC,mBAAmB,GAAGnR,SAAS;IACvDH,UAAU;QACR,IAAI,CAACuL,QAAQA,KAAKmF,MAAM,KAAK,QAAQY,mBAAmB;IAC1D,GAAG;QAAC/F;KAAK;IACTvL,UAAU;QACR,IAAIuL,CAAAA,wBAAAA,KAAMmF,MAAM,MAAK,QAAQU,mBAAmBtG,OAAO,GAAG;IAC5D,GAAG;QAACS,wBAAAA,KAAMmF,MAAM;KAAC;IACjB1Q,UAAU;QACR,IAAI,CAAC+L,QAAQwF,SAAS,IAAIxF,QAAQyF,MAAM,EAAE;QAC1C,IAAIjG,wBAAAA,KAAM0F,QAAQ,CAACQ,IAAI,CAAC,CAACC,UAAYA,QAAQhB,MAAM,KAAK,aAAagB,QAAQC,MAAM,KAAK,iBAAiB;YACvG;QACF;QACA,IAAIpG,CAAAA,wBAAAA,KAAMmF,MAAM,MAAK,QAAQ;QAC7B,IAAI,CAACS,SAASpM,MAAM,IAAI,CAACqM,mBAAmBtG,OAAO,EAAE;QACrD,MAAM8G,QAAQC,WAAW;YACvBT,mBAAmBtG,OAAO,GAAGqG,SAASpM,MAAM,GAAG;YAC/C,KAAKgH,QAAQ+F,IAAI,CACfX,SAASpM,MAAM,GACX;gBACEgN,MAAM;gBACNC,MAAM;oBACJzI,OAAO4H,SAAS/E,GAAG,CAAC,CAACpG,OAAU;4BAC7BT,MAAMS,KAAKT,IAAI;2BACXS,KAAKR,YAAY,GAAG;4BAAEA,cAAcQ,KAAKR,YAAY;wBAAC,IAAI,CAAC;4BAC/DlB,UAAU0B,KAAK1B,QAAQ;4BACvB2N,aAAajM,KAAKP,eAAe,GAAGO,KAAK1B,QAAQ;;oBAEnDqJ;oBACAG;oBACAoE,UAAU3G,OAAO7F,KAAKyM,GAAG,CAAC,GAAG5G,KAAKoF,UAAU,GAAG5C,iBAAiB;oBAChE4C,YAAYpF,OAAOA,KAAKoF,UAAU,GAAG5C;mBACjCxC,OACA;oBACEsF,WAAWtF,KAAKsF,SAAS;oBACzBC,UAAUvF,KAAKuF,QAAQ;oBACvBE,UAAUjP,mBAAmBwJ,MAAM8F;gBACrC,IACA,CAAC;YAET,IACA;gBAAEU,MAAM;YAAO;QAEvB,GAAG;QACH,OAAO,IAAMK,aAAaR;IAC5B,GAAG;QAAC7F;QAASoF;QAAU5F;QAAMoC;QAAYG;QAAeC;QAAesD;KAAgB;IAEvF,MAAMgB,gBAAgBpQ,yBAAyB0E;IAC/C,MAAM2L,iBAAiB,CAAC/J,0BACtB,KAACjJ;QAAW8E,SAAQ;QAAQmO,OAAM;kBAC/B;SAED1L,gBAAgB9B,MAAM,KAAK,IAC7ByD,UAAUzD,MAAM,GAAG,kBACjB,KAACzF;QAAW8E,SAAQ;QAAQmO,OAAM;kBAC/B;SAGH,wDAAwD;kBACxD,MAACnT;QAAMoT,SAAS;QAAGC,IAAI;YAAEC,YAAY;QAAa;;0BAChD,KAACpT;gBAAW8E,SAAQ;gBAAQmO,OAAM;0BAC/B;;YAEFF,8BACC,KAACpT;gBAAO0T,MAAK;gBAAQvO,SAAQ;gBAAWwO,MAAMP;0BAC3C;iBAED;;SAGNxL,gBAAgB9B,MAAM,GAAG,kBAC3B,KAAC1F;QACCsF,OAAM;QACNhC,OAAO4D;QACPsM,UAAU,CAACC,QAAU7I,cAAc6I,MAAMC,MAAM,CAACpQ,KAAK;QACrDgQ,MAAK;QACLK,MAAM;QACNC,UAAUC,QAAQ3H;kBAEjB1E,gBAAgBuF,GAAG,CAAC,CAAC/B,yBACpB,KAAClL;gBAA4BwD,OAAO0H,SAASjF,GAAG;0BAC7CiF,SAAS9E,IAAI;eADD8E,SAASjF,GAAG;uBAM/B,KAAC9F;QAAW8E,SAAQ;QAAQmO,OAAM;mBAC/B1L,oBAAAA,eAAe,CAAC,EAAE,qBAAlBA,kBAAoBtB,IAAI;;IAI7B;;;;;GAKC,GACD,MAAM4N,eAAejT,OAA8B;IACnDF,UAAU;QACR,MAAMoT,OAAOD,aAAarI,OAAO;QACjC,IAAIzD,QAAQ,CAAC+L,MAAM,OAAOlO;QAC1B,MAAMmO,OAAOC,SAASC,eAAe;QACrC,MAAMC,WAAW;QACjB,MAAMC,UAAU;YACdJ,KAAKK,KAAK,CAACC,WAAW,CAACH,UAAU,GAAG9N,KAAKC,KAAK,CAACyN,KAAKQ,qBAAqB,GAAGC,MAAM,IAAI,GAAG,EAAE,CAAC;QAC9F;QACAJ;QACA,MAAMK,WAAW,OAAOC,mBAAmB,cAAc,OAAO,IAAIA,eAAeN;QACnFK,4BAAAA,SAAUE,OAAO,CAACZ;QAClB,OAAO;YACLU,4BAAAA,SAAUG,UAAU;YACpBZ,KAAKK,KAAK,CAACQ,cAAc,CAACV;QAC5B;IACF,GAAG;QAACnM;KAAK;IAET,MAAM8M,8BACJ,MAAC/U;QAAMoT,SAAS;QAAKC,IAAI;YAAE2B,WAAW;YAAGC,MAAM;QAAE;;0BAC/C,MAACjV;gBAAMkV,WAAU;gBAAM9B,SAAS;gBAAGC,IAAI;oBAAEC,YAAY;gBAAS;;kCAC5D,KAACpT;wBAAW8E,SAAQ;wBAAKqO,IAAI;4BAAE4B,MAAM;wBAAE;kCACpC;;oBAEF9N,2BACC,KAACtH;wBACC0T,MAAK;wBACL4B,SAAS,IAAM,KAAKjG,YAAYkG,IAAI,CAACjO,YAAY;kCAEhDwF,QAAQwF,SAAS,GAAG,sBAAsB;yBAE3C;;;YAELe;YACA,UAACnK,gCAAAA,aAAcpD,MAAM,oBAAI,KAAK,kBAC7B,KAAC1F;gBACCsF,OAAM;gBACNhC,OAAOoH;gBACP8I,UAAU,CAACC,QAAU9I,cAAc8I,MAAMC,MAAM,CAACpQ,KAAK;gBACrDgQ,MAAK;gBACLK,MAAM;gBACNC,UAAUC,QAAQ3H;0BAEjB,CAACpD,uBAAAA,eAAgB,EAAE,EAAEiE,GAAG,CAAC,CAACqI,yBACzB,KAACtV;wBAA4BwD,OAAO8R,SAASrP,GAAG;kCAC7CqP,SAASlP,IAAI;uBADDkP,SAASrP,GAAG;iBAK7B;YACHmB,2BACC,KAACnF;gBACCkF,QAAQA;gBACRC,YAAYA;eACP4D,eAAe;gBAAEA;YAAa,IAAI,CAAC;gBACxCI,SAASA;gBACTmK,YAAY,CAACC;wBAGyBA;2BAFpC/K,YACE+K,SAAS7K,KAAK,IAAI6K,SAASpP,IAAI,GAC3B;wBAAE1B,MAAM;wBAAQwB,IAAI;wBAAIE,IAAI,GAAEoP,iBAAAA,SAASpP,IAAI,YAAboP,iBAAiB;wBAAI7K,OAAO6K,SAAS7K,KAAK;wBAAE8K,OAAO;oBAAK,IACtF;;kBAIR;0BACJ,KAAC7T;gBACCwI,OAAOgC,OAAOE,YAAYlC;gBAC1BgE,YAAYhC,OAAO,EAAE,GAAGgC;gBACxBsH,YAAY,CAACC,OAAOxQ,WAClBkF,SAAS,CAACkF,OACRpK,YAAY,IACRoK,KAAKxF,MAAM,CAAC,CAAC6L,OAAOC,KAAOA,OAAOF,SAClCpG,KAAKtC,GAAG,CAAC,CAACpG,MAAMgP,KAAQA,OAAOF,QAAQ,aAAK9O;gCAAM1B,UAAUoB,KAAKwG,GAAG,CAAC,IAAI5H;iCAAc0B;gBAG/FiP,UAAU,CAACH,QAAUtL,SAAS,CAACkF,OAASA,KAAKxF,MAAM,CAAC,CAAC6L,OAAOC,KAAOA,OAAOF;gBAC1EI,QAAQ,CAACJ;wBAGFhG;oBAFL,MAAM9I,OAAOuD,KAAK,CAACuL,MAAM;oBACzB,MAAM5Q,UAAU8B,QACX8I,4BAAAA,aAAahE,OAAO,CAAC0C,GAAG,CAACxH,KAAKb,SAAS,aAAvC2J,4BAA4CzB,aAAaG,GAAG,CAACxH,KAAKb,SAAS,IAC5ED;oBACJ,IAAI,CAACc,QAAQ,CAAC9B,SAAS;oBACvB2K,aAAa;wBACX3K;wBACAiR,WAAWL;wBACX5F,SAAS,aACHlJ,KAAKV,SAAS,GAAG;4BAAEA,WAAWU,KAAKV,SAAS;wBAAC,IAAI,CAAC,GAClDU,KAAK3B,SAAS,GAAG;4BAAEA,WAAW2B,KAAK3B,SAAS;wBAAC,IAAI,CAAC;4BACtDC,UAAU0B,KAAK1B,QAAQ;;oBAE3B;gBACF;gBACAmF,aAAaA;gBACb2L,eAAe1L;gBACfC,UACE4B,OAAO,qBACL,KAACrK;oBACCoF,QAAQA;oBACR3D,OAAOgH;oBACPkJ,UAAUjJ;oBACVrD,YAAYA;mBACPgE,QAAQmC,SAAS,GAAG;oBAAEC,kBAAkBpC,QAAQmC,SAAS;gBAAC,IAAI,CAAC;gBAI1E2I,QAAQnC,QAAQ3H;;YAEjBA,QAAQrE,OACPqE,KAAKmF,MAAM,KAAK,uBACd,KAAC9O;gBACCsF,MAAMA;gBACNZ,QAAQA;gBACRiF,MAAMA;gBACNZ,SAASA;gBACToB,SAASA;gBACTuJ,WAAWpE;gBACX3K,YAAYA;eACP4D,eAAe;gBAAEA;YAAa,IAAI,CAAC,GACnCI,QAAQA,OAAO,GAAG;gBAAEgL,aAAahL,QAAQA,OAAO,CAAChF,IAAI;YAAC,IAAI,CAAC;gBAChE0I,QAAQA;gCAGV,KAACpM;gBACCqF,MAAMA;gBACNZ,QAAQA;gBACRC,YAAYA;gBACZgF,MAAMA;gBACNZ,SAASA;gBACT6K,OAAOlM;gBACPyC,SAASA;gBACT0J,QAAQjK;gBACRkK,UAAU;oBACRlK,QAAQ;oBACRE,aAAa,EAAE;gBACjB;gBACAiK,aAAarE;eACR/G,QAAQmC,SAAS,GAAG;gBAAEC,kBAAkBpC,QAAQmC,SAAS;YAAC,IAAI,CAAC;gBACpEuB,QAAQA;gBACRnH,SAASA,QAAQA,OAAO;eACnBA,QAAQwB,KAAK,GACd;gBACEsN,eAAe;oBACb,4DAA4D;oBAC5D,wDAAwD;oBACxD7I,cAAcjC,OAAO,CAAC+K,IAAI,CAACtK,KAAK2B,OAAO;oBACvC1B,QAAQ;oBACRE,aAAa,EAAE;oBACfoB,mBAAmB;gBACrB;YACF,IACA,CAAC,oBAIT;;kCACE,MAAC9N;wBAAIyT,IAAI;4BAAE1G,SAAS;4BAAQ+J,gBAAgB;wBAAgB;;0CAC1D,KAACxW;gCAAW8E,SAAQ;0CAAM;;0CAC1B,KAAC9E;gCAAW8E,SAAQ;0CAAMtD,IAAIiN;;;;kCAEhC,KAACzO;wBAAW8E,SAAQ;wBAAUmO,OAAM;kCACjC;;kCAEH,KAACtT;wBACCmF,SAAQ;wBACRuO,MAAK;wBACLM,UAAUtH,WAAWpC,MAAMxE,MAAM,KAAK,KAAK,CAACwB;wBAC5CgO,SAAS,IAAM,KAAKhE;wBACpBkC,IAAI;4BAAE2B,WAAW;wBAAG;kCAEnBzI,UACG,aACA7E,QAAQA,OAAO,GACb,CAAC,KAAK,EAAEhG,cAAIgG,qBAAAA,QAAQiP,SAAS,CAACxM,OAAOE,iCAAzB3C,mBAAuC6J,UAAU,oBAAI5C,eAAe,UAAU,CAAC,GAC3F,CAAC,OAAO,EAAEjN,IAAIiN,gBAAgB;;oBAErCtD,4BACC,KAACtJ;wBACCmF,QAAQA;wBACR4G,SAASzC,YAAYyC,OAAO;uBACvB/C,eAAe;wBAAEA;oBAAa,IAAI,CAAC,GACnCI,QAAQA,OAAO,GAAG;wBAAEgL,aAAahL,QAAQA,OAAO,CAAChF,IAAI;oBAAC,IAAI,CAAC,MAEhE;;;;;IAMZ,qBACE;;0BACE,KAAC7G;gBAAcsX,QAAQ;;0BACvB,MAAChX;gBACCiX,KAAKhK,KAAKgK,GAAG;gBACbxD,IAAI;oBACF1G,SAAS;oBACT,8DAA8D;oBAC9D,oEAAoE;oBACpE,mCAAmC;oBACnC8H,QAAQ5H,KAAK4H,MAAM;oBACnBqC,UAAU;gBACZ;;kCAEA,MAAClX;wBAAIyT,IAAI;4BAAE4B,MAAM;4BAAG8B,GAAG;4BAAGC,WAAW;4BAAQC,IAAIhP,OAAO,IAAI;wBAAG;;0CAC7D,KAACrI;gCAAIyT,IAAI;oCAAE6D,IAAI;oCAAG,WAAW;wCAAEvK,SAAS;oCAAO;gCAAE;0CAC/C,cAAA,KAAC1J;oCAAiByE,SAASA;;;4BAG5BP,2BACC,KAACzE;gCACCoF,MAAMA;gCACNZ,QAAQA;gCACRC,YAAYA;gCACZ0M,UAAUC,QAAQ3H;gCAClBgL,QAAQ,CAAC9H,MAAM+H;oCACb9K,aAAa8K;oCACbhL,QAAQiD;oCACR3C,aAAa;gCACf;gCACAmC,QAAQA;iCAER;4BAEHlH,2BAAa,KAACb;gCAAcE,UAAUW;gCAAYT,QAAQA;gCAAQC,YAAYA,cAAc;iCAAW;0CACxG,KAAC9E;gCACCuB,QAAQA;gCACRyT,UAAUjP;gCACVkP,eAAe,IAAM,KAAKvG;gCAC1BC,eAAeA;gCACfuG,YAAY,CAACzO,uBAAAA,eAAgB,EAAE,EAAEkE,GAAG,CAAC,CAACwK;wCAEvBA;2CAF0C;wCACvDxR,KAAKwR,SAASxR,GAAG;wCACjBG,MAAMqD,QAAOgO,iBAAAA,SAASrR,IAAI,YAAbqR,iBAAiB;oCAChC;;gCACArT,YAAYA;gCACZsT,YAAYhP;gCACZiP,SAAS/O,SAAS+O,OAAO;gCACzBxQ,QAAQA;gCACR6F,UAAUgB;gCACVgC,cAAcA;gCACd4H,OAAO,CAAC7S;oCACN,IAAIqH,MAAM,OAAO,KAAK0C,OAAO,sCAAsC;oCACnEc,WAAW7K;gCACb;;;;oBAGHmD,qBACC,KAACrI;wBACCyT,IAAI;4BACFuE,OAAO;gCAAEC,IAAI;gCAAKC,IAAI;4BAAI;4BAC1BC,YAAY;4BACZC,aAAa;4BACbrL,SAAS;4BACTsL,eAAe;4BACflB,GAAG;4BACHC,WAAW;wBACb;kCAECjC;yBAED;;;YAEL,CAAC9M,qBACA;;kCACE,MAACrI;wBACCiX,KAAK9C;wBACLV,IAAI;4BACF6E,UAAU;4BACVC,MAAM;4BACNC,OAAO;4BACPC,QAAQ;4BACRtB,GAAG;4BACHuB,SAAS;4BACTC,WAAW;4BACXP,aAAa;4BACbrL,SAAS;4BACT6L,KAAK;4BACLlF,YAAY;4BACZmF,QAAQzQ,MAAMyQ,MAAM,CAACC,MAAM;wBAC7B;;0CAEA,KAAC/Y;gCAAMgZ,cAAc/J;gCAAOuE,OAAM;0CAChC,cAAA,KAACtT;oCACCmF,SAAQ;oCACRmQ,SAAS,IAAMzI,aAAa;oCAC5B2G,IAAI;wCAAE2B,WAAW5S;oCAAa;8CAE7B+J,OAAO,YAAY;;;0CAGxB,KAACjM;gCAAW8E,SAAQ;gCAAKqO,IAAI;oCAAE4B,MAAM;oCAAG2D,WAAW;gCAAQ;0CACxDlX,IAAIyK,OAAOA,KAAKuF,QAAQ,GAAG/C;;4BAE7B,CAACxC,qBACA,KAACtM;gCACCmF,SAAQ;gCACR6O,UAAUtH,WAAWpC,MAAMxE,MAAM,KAAK,KAAK,CAACwB;gCAC5CgO,SAAS,IAAM,KAAKhE;gCACpBkC,IAAI;oCAAE2B,WAAW5S;gCAAa;0CAE7B;iCAED;;;kCAEN,KAACtC;wBACC+Y,QAAO;wBACPzD,MAAM3I;wBACNqM,SAAS,IAAMpM,aAAa;wBAC5BqM,WAAW;4BAAEC,OAAO;gCAAE3F,IAAI;oCAAE4F,WAAW;oCAASlC,GAAG;oCAAGmC,qBAAqB;oCAAIC,sBAAsB;gCAAG;4BAAE;wBAAE;kCAE3GpE;;;iBAGH;0BACJ,KAACzS;gBACCwC,OAAO,WAAE0K,6BAAAA,UAAW1K,OAAO,oBAAI;gBAC/BgL,OAAO,EAAEN,6BAAAA,UAAWM,OAAO;gBAC3BgJ,SAAS,IAAMrJ,aAAa;gBAC5B2J,WAAW,CAACrU;oBACV,MAAMsU,QAAQ7J;oBACdC,aAAa;oBACb,IAAI,CAAC4J,OAAO;oBACZ,IAAIA,MAAMtD,SAAS,KAAKjQ,WAAW;wBACjCsJ,WAAWiK,MAAMvU,OAAO,EAAEC,OAAOC,OAAO,EAAED,OAAOE,SAAS,EAAEF,OAAOG,QAAQ;wBAC3E;oBACF;oBACA,MAAM0Q,KAAKyD,MAAMtD,SAAS;oBAC1B3L,SAAS,CAACkF,OACRA,KAAKtC,GAAG,CAAC,CAACpG,MAAM8O,QAAWA,UAAUE,KAAK/Q,gBAAgBwU,MAAMvU,OAAO,EAAEC,UAAU6B;gBAEvF;eACK4I,CAAAA,6BAAAA,UAAWuG,SAAS,MAAKjQ,YAC1B;gBACE+P,UAAU;oBACR,MAAMD,KAAKpG,UAAUuG,SAAS;oBAC9BtG,aAAa;oBACbrF,SAAS,CAACkF,OAASA,KAAKxF,MAAM,CAAC,CAAC6L,OAAOD,QAAUA,UAAUE;gBAC7D;YACF,IACA,CAAC;0BAEP,KAAC1S;gBACCkS,MAAM3H;gBACN/F,SAASA;gBACTR,QAAQA;gBACRiD,OAAOA;gBACPE,aAAaA;gBACbE,UAAUA;eACLQ,eAAe;gBAAEA;YAAa,IAAI,CAAC,GACnCI,QAAQA,OAAO,GAAG;gBAAEgL,aAAahL,QAAQA,OAAO,CAAChF,IAAI;YAAC,IAAI,CAAC;gBAChE2S,SAAS,IAAMpL,mBAAmB;gBAClC4L,QAAQ,IAAMxT;gBACdyT,QAAQ;oBACN7L,mBAAmB;oBACnBtD,SAAS,EAAE;oBACXE,eAAe;oBACfE,YAAY;oBACZkC,aAAa;gBACf;;YAEDwC,YAAYsK,MAAM;;;AAGzB;AACAlS,eAAemS,WAAW,GAAG;AAE7B,eAAenS,eAAc"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface PosReaderSplashSettingProps {
|
|
2
|
+
hostId: string;
|
|
3
|
+
/** Whether the viewer may change the site's readers (`managePos`, admin or editor). */
|
|
4
|
+
canManagePos: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* "Reader start-up screen" on the POS devices card (AGL-4048): what the
|
|
8
|
+
* store's Stripe smart readers show while they wait for a payment. The
|
|
9
|
+
* platform's default screen, the workspace's logo on a white screen, or a
|
|
10
|
+
* full-screen portrait image from the media library. A white-label
|
|
11
|
+
* workspace is never offered the platform's screen and shows its own logo
|
|
12
|
+
* unless it picks an image.
|
|
13
|
+
*
|
|
14
|
+
* The server applies the choice to the store's readers when it is saved
|
|
15
|
+
* (and again when this opens and finds the logo changed since); readers
|
|
16
|
+
* pick it up within about ten minutes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function PosReaderSplashSetting({ hostId, canManagePos }: PosReaderSplashSettingProps): import("react").JSX.Element;
|
|
19
|
+
export declare namespace PosReaderSplashSetting {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
export default PosReaderSplashSetting;
|