@aglyn/plugins-commerce 1.0.0-beta.290 → 1.0.0-beta.292
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/package.json +13 -13
- package/src/lib/components/cart-fulfillment.d.ts +3 -0
- package/src/lib/components/cart-fulfillment.js.map +1 -1
- package/src/lib/components/cart.js +14 -4
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +2 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.d.ts +6 -0
- package/src/lib/components/console/host-orders-card.component.js +3 -2
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/invoice-send.component.d.ts +44 -0
- package/src/lib/components/console/invoice-send.component.js +237 -0
- package/src/lib/components/console/invoice-send.component.js.map +1 -0
- package/src/lib/components/console/order-detail-dialog.component.d.ts +5 -0
- package/src/lib/components/console/order-detail-dialog.component.js +9 -2
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-invoice.component.d.ts +9 -0
- package/src/lib/components/console/order-invoice.component.js +27 -2
- package/src/lib/components/console/order-invoice.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-item-dialog.component.js +3 -2
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos-kiosk-page.component.js +2 -1
- package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +1 -1
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/product-add-ons-fields.component.d.ts +41 -0
- package/src/lib/components/console/product-add-ons-fields.component.js +356 -0
- package/src/lib/components/console/product-add-ons-fields.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +31 -5
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-register-fields.component.d.ts +4 -5
- package/src/lib/components/console/product-register-fields.component.js +8 -197
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-zone.component.js +6 -0
- package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
- package/src/lib/components/console/quote-editor-dialog.component.d.ts +29 -0
- package/src/lib/components/console/quote-editor-dialog.component.js +102 -4
- package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/quote-pay-link.component.d.ts +8 -1
- package/src/lib/components/console/quote-pay-link.component.js +29 -3
- package/src/lib/components/console/quote-pay-link.component.js.map +1 -1
- package/src/lib/components/console/quote-proofs.component.d.ts +11 -0
- package/src/lib/components/console/quote-proofs.component.js +68 -0
- package/src/lib/components/console/quote-proofs.component.js.map +1 -1
- package/src/lib/components/console/quote-send.component.d.ts +42 -0
- package/src/lib/components/console/quote-send.component.js +304 -0
- package/src/lib/components/console/quote-send.component.js.map +1 -0
- package/src/lib/components/console/quote-start.component.d.ts +45 -0
- package/src/lib/components/console/quote-start.component.js +182 -0
- package/src/lib/components/console/quote-start.component.js.map +1 -0
- package/src/lib/components/product-add-ons.d.ts +28 -0
- package/src/lib/components/product-add-ons.js +136 -0
- package/src/lib/components/product-add-ons.js.map +1 -0
- package/src/lib/components/product-detail.d.ts +16 -0
- package/src/lib/components/product-detail.js +112 -19
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-grid.d.ts +8 -2
- package/src/lib/components/product-grid.js +6 -1
- package/src/lib/components/product-grid.js.map +1 -1
- package/src/lib/components/product-options-field-body.d.ts +44 -0
- package/src/lib/components/product-options-field-body.js +260 -0
- package/src/lib/components/product-options-field-body.js.map +1 -0
- package/src/lib/components/product-options-field.d.ts +32 -0
- package/src/lib/components/product-options-field.js +128 -0
- package/src/lib/components/product-options-field.js.map +1 -0
- package/src/lib/components/quote-page-body.js +39 -20
- package/src/lib/components/quote-page-body.js.map +1 -1
- package/src/lib/model/commerce-cart.d.ts +15 -3
- package/src/lib/model/commerce-cart.js +10 -3
- package/src/lib/model/commerce-cart.js.map +1 -1
- package/src/lib/model/commerce-invoices.d.ts +139 -0
- package/src/lib/model/commerce-invoices.js +343 -0
- package/src/lib/model/commerce-invoices.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +35 -5
- package/src/lib/model/commerce-orders.js +3 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-kiosk.d.ts +1 -1
- package/src/lib/model/commerce-pos-kiosk.js +3 -2
- package/src/lib/model/commerce-pos-kiosk.js.map +1 -1
- package/src/lib/model/commerce-product-field.d.ts +23 -0
- package/src/lib/model/commerce-product-field.js +26 -0
- package/src/lib/model/commerce-product-field.js.map +1 -0
- package/src/lib/model/commerce-quote-email.d.ts +81 -0
- package/src/lib/model/commerce-quote-email.js +170 -0
- package/src/lib/model/commerce-quote-email.js.map +1 -0
- package/src/lib/model/commerce-quote-pay.d.ts +49 -6
- package/src/lib/model/commerce-quote-pay.js +69 -36
- package/src/lib/model/commerce-quote-pay.js.map +1 -1
- package/src/lib/model/commerce-quote-request.d.ts +93 -0
- package/src/lib/model/commerce-quote-request.js +207 -0
- package/src/lib/model/commerce-quote-request.js.map +1 -0
- package/src/lib/model/commerce-quotes.d.ts +81 -0
- package/src/lib/model/commerce-quotes.js +1 -1
- package/src/lib/model/commerce-quotes.js.map +1 -1
- package/src/lib/model/commerce.d.ts +18 -0
- package/src/lib/model/commerce.js +26 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +3 -0
- package/src/lib/model/index.js +3 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/product-modifiers.d.ts +74 -4
- package/src/lib/model/product-modifiers.js +131 -10
- package/src/lib/model/product-modifiers.js.map +1 -1
- package/src/lib/plugin.js +19 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/billing-webhook.js +164 -98
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cart-checkout.js +14 -2
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.d.ts +5 -0
- package/src/lib/server/cart.js +41 -4
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/catalog.d.ts +6 -0
- package/src/lib/server/catalog.js +2 -0
- package/src/lib/server/catalog.js.map +1 -1
- package/src/lib/server/checkout-extras.js +3 -1
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +28 -3
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/commerce-pdf.d.ts +5 -1
- package/src/lib/server/commerce-pdf.js +37 -10
- package/src/lib/server/commerce-pdf.js.map +1 -1
- package/src/lib/server/draft-order.js +23 -3
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/invoice-email.d.ts +76 -0
- package/src/lib/server/invoice-email.js +183 -0
- package/src/lib/server/invoice-email.js.map +1 -0
- package/src/lib/server/local-fulfillment.js +5 -1
- package/src/lib/server/local-fulfillment.js.map +1 -1
- package/src/lib/server/order-invoice-send.d.ts +43 -0
- package/src/lib/server/order-invoice-send.js +218 -0
- package/src/lib/server/order-invoice-send.js.map +1 -0
- package/src/lib/server/order-status.d.ts +11 -0
- package/src/lib/server/order-status.js +44 -8
- package/src/lib/server/order-status.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +3 -2
- package/src/lib/server/person-eraser.js +25 -6
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-offline-sync.js +1 -1
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-order.js +1 -1
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/product.d.ts +26 -0
- package/src/lib/server/product.js +18 -0
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/products-write.js +5 -2
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server/quote-email.d.ts +85 -0
- package/src/lib/server/quote-email.js +211 -0
- package/src/lib/server/quote-email.js.map +1 -0
- package/src/lib/server/quote-link-token.d.ts +11 -0
- package/src/lib/server/quote-link-token.js +21 -0
- package/src/lib/server/quote-link-token.js.map +1 -1
- package/src/lib/server/quote-pay.d.ts +8 -3
- package/src/lib/server/quote-pay.js +105 -43
- package/src/lib/server/quote-pay.js.map +1 -1
- package/src/lib/server/quote.d.ts +11 -0
- package/src/lib/server/quote.js +309 -12
- package/src/lib/server/quote.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +2 -1
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +5 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +8 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/tenant-emails.js +243 -0
- package/src/lib/tenant-emails.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +8 -0
- package/src/lib/utils/add-to-cart.js +10 -2
- package/src/lib/utils/add-to-cart.js.map +1 -1
- package/src/lib/utils/commerce-document-pdf.d.ts +5 -0
- package/src/lib/utils/commerce-document-pdf.js +6 -1
- package/src/lib/utils/commerce-document-pdf.js.map +1 -1
- package/src/lib/utils/invoice-email-content.d.ts +45 -0
- package/src/lib/utils/invoice-email-content.js +126 -0
- package/src/lib/utils/invoice-email-content.js.map +1 -0
- package/src/lib/utils/order-invoice.d.ts +1 -1
- package/src/lib/utils/order-invoice.js +14 -6
- package/src/lib/utils/order-invoice.js.map +1 -1
- package/src/lib/utils/quote-email-content.d.ts +63 -0
- package/src/lib/utils/quote-email-content.js +157 -0
- package/src/lib/utils/quote-email-content.js.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos/pos-item-dialog.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 {\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n IconButton,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport { useEffect, useMemo, useState } from 'react'\nimport * as CommerceModel from '../../../model'\nimport { usd } from './pos-api'\nimport { POS_TOUCH_PX } from './pos-product-grid.component'\n\n/** What the dialog hands back: one basket line's worth of choices. */\nexport interface PosItemChoice {\n variant: CommerceModel.ProductVariant\n modifiers: CommerceModel.ModifierSelection[]\n quantity: number\n}\n\nexport interface PosItemDialogProps {\n /** The product being added or edited; `null` closes the dialog. */\n product: (CommerceModel.HostProduct & { $id: string }) | null\n /** An existing line's choices, when the cashier tapped a basket line. */\n initial?: { variantId?: string; modifiers?: CommerceModel.ModifierSelection[]; quantity: number }\n onClose: () => void\n onConfirm: (choice: PosItemChoice) => void\n /** Editing only: takes the line out of the basket. */\n onRemove?: () => void\n /**\n * How a price reads; the register's dollars by default. The self-service\n * kiosk (AGL-3623) passes the store's currency.\n */\n formatMoney?: (cents: number) => string\n /**\n * A sold-out variant cannot be added, rather than warned about: a kiosk's\n * customer is not holding the goods the way a cashier is (AGL-3623).\n */\n blockSoldOut?: boolean\n /** The most of one line that can be added; 99 at the register. */\n maxQuantity?: number\n}\n\n/** Whether the register must ask before adding: a choice of variant or any modifier. */\nexport function posItemNeedsChoice(product: CommerceModel.HostProduct): boolean {\n return (\n (product.variants?.length ?? 0) > 1 ||\n CommerceModel.productModifierGroups(product).length > 0\n )\n}\n\n/** The variant whose options match every picked value, or undefined. */\nfunction variantFor(\n product: CommerceModel.HostProduct,\n picked: Record<string, string>,\n): CommerceModel.ProductVariant | undefined {\n return product.variants.find((variant) =>\n (product.options ?? []).every((option) => variant.options?.[option.name] === picked[option.name]),\n )\n}\n\nfunction variantLabel(variant: CommerceModel.ProductVariant): string {\n return Object.values(variant.options ?? {}).join(' / ') || 'Default'\n}\n\nfunction soldOut(variant: CommerceModel.ProductVariant | undefined): boolean {\n return variant?.inventory != null && variant.inventory <= 0\n}\n\n/**\n * The register's item sheet (AGL-3607): the size, color or other variant,\n * then each modifier group — required ones marked, \"pick one\" groups as a\n * single toggle row and \"pick up to N\" groups as chips — and the quantity,\n * with the line's price on the Add button as it changes. Full screen on a\n * phone, a dialog on a tablet; every target is at least 44px.\n *\n * The price shown is the register's estimate. The server prices the line\n * again from the product when the sale is charged.\n */\nexport function PosItemDialog(props: PosItemDialogProps) {\n const { product, initial } = props\n const money = props.formatMoney ?? usd\n const maxQuantity = props.maxQuantity ?? 99\n const theme = useTheme()\n const phone = useMediaQuery(theme.breakpoints.down('sm'))\n const groups = useMemo(\n () => (product ? CommerceModel.productModifierGroups(product) : []),\n [product],\n )\n const options = product?.options ?? []\n const [picked, setPicked] = useState<Record<string, string>>({})\n const [variantId, setVariantId] = useState('')\n const [modifiers, setModifiers] = useState<CommerceModel.ModifierSelection[]>([])\n const [quantity, setQuantity] = useState(1)\n\n useEffect(() => {\n if (!product) return\n const start =\n product.variants.find((variant) => variant.id === initial?.variantId) ??\n product.variants.find((variant) => !soldOut(variant)) ??\n product.variants[0]\n setVariantId(start?.id ?? '')\n setPicked({ ...(start?.options ?? {}) })\n setModifiers(initial?.modifiers ?? [])\n setQuantity(initial?.quantity ?? 1)\n }, [product, initial])\n\n if (!product) return null\n\n const variant =\n options.length > 0\n ? variantFor(product, picked)\n : product.variants.find((item) => item.id === variantId)\n const chosen = CommerceModel.resolveLineModifiers(product, modifiers)\n const unitCents = variant\n ? Math.round(Number(variant.priceUsd) * 100) + (chosen.ok ? chosen.extraCents : 0)\n : 0\n const missing = groups.find(\n (group) => modifiers.filter((pick) => pick.groupId === group.id).length < group.min,\n )\n const canAdd =\n Boolean(variant) && chosen.ok && quantity >= 1 && !(props.blockSoldOut && soldOut(variant))\n\n const toggle = (group: CommerceModel.ProductModifierGroup, optionId: string) => {\n setModifiers((current) => {\n const inGroup = current.filter((pick) => pick.groupId === group.id)\n const has = inGroup.some((pick) => pick.optionId === optionId)\n if (has) return current.filter((pick) => !(pick.groupId === group.id && pick.optionId === optionId))\n // A pick-one group swaps its choice; a pick-many group stops at its max.\n if (group.max === 1) {\n return [...current.filter((pick) => pick.groupId !== group.id), { groupId: group.id, optionId }]\n }\n if (inGroup.length >= group.max) return current\n return [...current, { groupId: group.id, optionId }]\n })\n }\n\n return (\n <Dialog open onClose={props.onClose} fullScreen={phone} fullWidth maxWidth=\"sm\">\n <DialogTitle>{product.name}</DialogTitle>\n <DialogContent dividers>\n <Stack spacing={3}>\n {options.length > 0\n ? options.map((option) => (\n <Box key={option.name} role=\"group\" aria-label={option.name}>\n <Typography variant=\"subtitle1\" component=\"h3\" sx={{ mb: 1 }}>\n {option.name}\n </Typography>\n <ToggleButtonGroup\n exclusive\n value={picked[option.name] ?? null}\n onChange={(_event, value: string | null) => {\n if (value) setPicked((current) => ({ ...current, [option.name]: value }))\n }}\n sx={{ flexWrap: 'wrap', gap: 1 }}\n >\n {option.values.map((value) => (\n <ToggleButton key={value} value={value} sx={{ minHeight: POS_TOUCH_PX, minWidth: 88 }}>\n {value}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Box>\n ))\n : product.variants.length > 1 ? (\n <Box role=\"group\" aria-label=\"Variant\">\n <ToggleButtonGroup\n exclusive\n value={variantId || null}\n onChange={(_event, value: string | null) => value && setVariantId(value)}\n sx={{ flexWrap: 'wrap', gap: 1 }}\n >\n {product.variants.map((item) => (\n <ToggleButton key={item.id} value={item.id} sx={{ minHeight: POS_TOUCH_PX, minWidth: 88 }}>\n {`${variantLabel(item)} · ${money(Math.round(Number(item.priceUsd) * 100))}`}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Box>\n ) : null}\n {options.length > 0 && !variant ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {'That combination is not sold. Pick another.'}\n </Typography>\n ) : null}\n {variant && soldOut(variant) ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {props.blockSoldOut ? 'Sold out' : 'Out of stock: selling it takes the count below zero.'}\n </Typography>\n ) : null}\n {groups.map((group) => {\n const count = modifiers.filter((pick) => pick.groupId === group.id).length\n const rule = CommerceModel.modifierGroupRequired(group)\n ? group.max === 1\n ? 'Required · pick 1'\n : `Required · pick ${group.min} to ${group.max}`\n : group.max === 1\n ? 'Optional · pick 1'\n : `Optional · up to ${group.max}`\n return (\n <Box key={group.id} role=\"group\" aria-label={group.name}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'baseline', mb: 1 }}>\n <Typography variant=\"subtitle1\" component=\"h3\">\n {group.name}\n </Typography>\n <Typography\n variant=\"caption\"\n color={count < group.min ? 'warning.main' : 'text.secondary'}\n >\n {rule}\n </Typography>\n </Stack>\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>\n {group.options.map((option) => {\n const selected = modifiers.some(\n (pick) => pick.groupId === group.id && pick.optionId === option.id,\n )\n return (\n <Chip\n key={option.id}\n label={option.priceCents ? `${option.name} +${money(option.priceCents)}` : option.name}\n color={selected ? 'primary' : 'default'}\n variant={selected ? 'filled' : 'outlined'}\n aria-pressed={selected}\n onClick={() => toggle(group, option.id)}\n disabled={!selected && group.max > 1 && count >= group.max}\n sx={{ minHeight: POS_TOUCH_PX, px: 1 }}\n />\n )\n })}\n </Box>\n </Box>\n )\n })}\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h3\" sx={{ flex: 1 }}>\n {'Quantity'}\n </Typography>\n <IconButton\n aria-label=\"One fewer\"\n onClick={() => setQuantity((value) => Math.max(1, value - 1))}\n sx={{ width: POS_TOUCH_PX, height: POS_TOUCH_PX, border: 1, borderColor: 'divider' }}\n >\n {'−'}\n </IconButton>\n <TextField\n value={quantity}\n onChange={(event) => {\n const next = Math.round(Number(event.target.value.replace(/\\D/g, '')))\n setQuantity(Math.max(1, Math.min(maxQuantity, next || 1)))\n }}\n sx={{ width: 72 }}\n slotProps={{\n htmlInput: { inputMode: 'numeric', 'aria-label': 'Quantity', style: { textAlign: 'center' } },\n }}\n />\n <IconButton\n aria-label=\"One more\"\n onClick={() => setQuantity((value) => Math.min(maxQuantity, value + 1))}\n sx={{ width: POS_TOUCH_PX, height: POS_TOUCH_PX, border: 1, borderColor: 'divider' }}\n >\n {'+'}\n </IconButton>\n </Stack>\n </Stack>\n </DialogContent>\n <DialogActions sx={{ p: 2, gap: 1 }}>\n {props.onRemove ? (\n <Button color=\"error\" onClick={props.onRemove} sx={{ minHeight: POS_TOUCH_PX, mr: 'auto' }}>\n {'Remove'}\n </Button>\n ) : null}\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={!canAdd}\n onClick={() => {\n if (!variant || !chosen.ok) return\n props.onConfirm({ variant, modifiers, quantity })\n }}\n sx={{ minHeight: POS_TOUCH_PX, minWidth: 160 }}\n >\n {missing\n ? `Choose ${missing.name.toLowerCase()}`\n : `${props.onRemove ? 'Update' : 'Add'} · ${money(unitCents * quantity)}`}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nPosItemDialog.displayName = 'PosItemDialog'\n"],"names":["Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","IconButton","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useMediaQuery","useTheme","useEffect","useMemo","useState","CommerceModel","usd","POS_TOUCH_PX","posItemNeedsChoice","product","variants","length","productModifierGroups","variantFor","picked","find","variant","options","every","option","name","variantLabel","Object","values","join","soldOut","inventory","PosItemDialog","props","initial","money","formatMoney","maxQuantity","theme","phone","breakpoints","down","groups","setPicked","variantId","setVariantId","modifiers","setModifiers","quantity","setQuantity","start","id","item","chosen","resolveLineModifiers","unitCents","Math","round","Number","priceUsd","ok","extraCents","missing","group","filter","pick","groupId","min","canAdd","Boolean","blockSoldOut","toggle","optionId","current","inGroup","has","some","max","open","onClose","fullScreen","fullWidth","maxWidth","dividers","spacing","map","role","aria-label","component","sx","mb","exclusive","value","onChange","_event","flexWrap","gap","minHeight","minWidth","color","count","rule","modifierGroupRequired","direction","alignItems","display","selected","label","priceCents","aria-pressed","onClick","disabled","px","flex","width","height","border","borderColor","event","next","target","replace","slotProps","htmlInput","inputMode","style","textAlign","p","onRemove","mr","onConfirm","toLowerCase","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos/pos-item-dialog.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 {\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n IconButton,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@mui/material'\nimport { useEffect, useMemo, useState } from 'react'\nimport * as CommerceModel from '../../../model'\nimport { usd } from './pos-api'\nimport { POS_TOUCH_PX } from './pos-product-grid.component'\n\n/** What the dialog hands back: one basket line's worth of choices. */\nexport interface PosItemChoice {\n variant: CommerceModel.ProductVariant\n modifiers: CommerceModel.ModifierSelection[]\n quantity: number\n}\n\nexport interface PosItemDialogProps {\n /** The product being added or edited; `null` closes the dialog. */\n product: (CommerceModel.HostProduct & { $id: string }) | null\n /** An existing line's choices, when the cashier tapped a basket line. */\n initial?: { variantId?: string; modifiers?: CommerceModel.ModifierSelection[]; quantity: number }\n onClose: () => void\n onConfirm: (choice: PosItemChoice) => void\n /** Editing only: takes the line out of the basket. */\n onRemove?: () => void\n /**\n * How a price reads; the register's dollars by default. The self-service\n * kiosk (AGL-3623) passes the store's currency.\n */\n formatMoney?: (cents: number) => string\n /**\n * A sold-out variant cannot be added, rather than warned about: a kiosk's\n * customer is not holding the goods the way a cashier is (AGL-3623).\n */\n blockSoldOut?: boolean\n /** The most of one line that can be added; 99 at the register. */\n maxQuantity?: number\n}\n\n/** Whether the register must ask before adding: a choice of variant or any modifier. */\nexport function posItemNeedsChoice(product: CommerceModel.HostProduct): boolean {\n return (\n (product.variants?.length ?? 0) > 1 ||\n CommerceModel.productModifierGroups(product).length > 0\n )\n}\n\n/** The variant whose options match every picked value, or undefined. */\nfunction variantFor(\n product: CommerceModel.HostProduct,\n picked: Record<string, string>,\n): CommerceModel.ProductVariant | undefined {\n return product.variants.find((variant) =>\n (product.options ?? []).every((option) => variant.options?.[option.name] === picked[option.name]),\n )\n}\n\nfunction variantLabel(variant: CommerceModel.ProductVariant): string {\n return Object.values(variant.options ?? {}).join(' / ') || 'Default'\n}\n\nfunction soldOut(variant: CommerceModel.ProductVariant | undefined): boolean {\n return variant?.inventory != null && variant.inventory <= 0\n}\n\n/**\n * The register's item sheet (AGL-3607): the size, color or other variant,\n * then each modifier group — required ones marked, \"pick one\" groups as a\n * single toggle row and \"pick up to N\" groups as chips — and the quantity,\n * with the line's price on the Add button as it changes. Full screen on a\n * phone, a dialog on a tablet; every target is at least 44px.\n *\n * The price shown is the register's estimate. The server prices the line\n * again from the product when the sale is charged.\n */\nexport function PosItemDialog(props: PosItemDialogProps) {\n const { product, initial } = props\n const money = props.formatMoney ?? usd\n const maxQuantity = props.maxQuantity ?? 99\n const theme = useTheme()\n const phone = useMediaQuery(theme.breakpoints.down('sm'))\n const groups = useMemo(\n () => (product ? CommerceModel.productModifierGroups(product) : []),\n [product],\n )\n const options = product?.options ?? []\n const [picked, setPicked] = useState<Record<string, string>>({})\n const [variantId, setVariantId] = useState('')\n const [modifiers, setModifiers] = useState<CommerceModel.ModifierSelection[]>([])\n const [quantity, setQuantity] = useState(1)\n\n useEffect(() => {\n if (!product) return\n const start =\n product.variants.find((variant) => variant.id === initial?.variantId) ??\n product.variants.find((variant) => !soldOut(variant)) ??\n product.variants[0]\n setVariantId(start?.id ?? '')\n setPicked({ ...(start?.options ?? {}) })\n setModifiers(initial?.modifiers ?? [])\n setQuantity(initial?.quantity ?? 1)\n }, [product, initial])\n\n if (!product) return null\n\n const variant =\n options.length > 0\n ? variantFor(product, picked)\n : product.variants.find((item) => item.id === variantId)\n const chosen = CommerceModel.resolveLineModifiers(product, modifiers, variant?.id)\n const unitCents = variant\n ? Math.round(Number(variant.priceUsd) * 100) + (chosen.ok ? chosen.extraCents : 0)\n : 0\n const missing = groups.find(\n (group) => modifiers.filter((pick) => pick.groupId === group.id).length < group.min,\n )\n const canAdd =\n Boolean(variant) && chosen.ok && quantity >= 1 && !(props.blockSoldOut && soldOut(variant))\n\n const toggle = (group: CommerceModel.ProductModifierGroup, optionId: string) => {\n setModifiers((current) => {\n const inGroup = current.filter((pick) => pick.groupId === group.id)\n const has = inGroup.some((pick) => pick.optionId === optionId)\n if (has) return current.filter((pick) => !(pick.groupId === group.id && pick.optionId === optionId))\n // A pick-one group swaps its choice; a pick-many group stops at its max.\n if (group.max === 1) {\n return [...current.filter((pick) => pick.groupId !== group.id), { groupId: group.id, optionId }]\n }\n if (inGroup.length >= group.max) return current\n return [...current, { groupId: group.id, optionId }]\n })\n }\n\n return (\n <Dialog open onClose={props.onClose} fullScreen={phone} fullWidth maxWidth=\"sm\">\n <DialogTitle>{product.name}</DialogTitle>\n <DialogContent dividers>\n <Stack spacing={3}>\n {options.length > 0\n ? options.map((option) => (\n <Box key={option.name} role=\"group\" aria-label={option.name}>\n <Typography variant=\"subtitle1\" component=\"h3\" sx={{ mb: 1 }}>\n {option.name}\n </Typography>\n <ToggleButtonGroup\n exclusive\n value={picked[option.name] ?? null}\n onChange={(_event, value: string | null) => {\n if (value) setPicked((current) => ({ ...current, [option.name]: value }))\n }}\n sx={{ flexWrap: 'wrap', gap: 1 }}\n >\n {option.values.map((value) => (\n <ToggleButton key={value} value={value} sx={{ minHeight: POS_TOUCH_PX, minWidth: 88 }}>\n {value}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Box>\n ))\n : product.variants.length > 1 ? (\n <Box role=\"group\" aria-label=\"Variant\">\n <ToggleButtonGroup\n exclusive\n value={variantId || null}\n onChange={(_event, value: string | null) => value && setVariantId(value)}\n sx={{ flexWrap: 'wrap', gap: 1 }}\n >\n {product.variants.map((item) => (\n <ToggleButton key={item.id} value={item.id} sx={{ minHeight: POS_TOUCH_PX, minWidth: 88 }}>\n {`${variantLabel(item)} · ${money(Math.round(Number(item.priceUsd) * 100))}`}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Box>\n ) : null}\n {options.length > 0 && !variant ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {'That combination is not sold. Pick another.'}\n </Typography>\n ) : null}\n {variant && soldOut(variant) ? (\n <Typography variant=\"body2\" color=\"warning.main\">\n {props.blockSoldOut ? 'Sold out' : 'Out of stock: selling it takes the count below zero.'}\n </Typography>\n ) : null}\n {groups.map((group) => {\n const count = modifiers.filter((pick) => pick.groupId === group.id).length\n const rule = CommerceModel.modifierGroupRequired(group)\n ? group.max === 1\n ? 'Required · pick 1'\n : `Required · pick ${group.min} to ${group.max}`\n : group.max === 1\n ? 'Optional · pick 1'\n : `Optional · up to ${group.max}`\n return (\n <Box key={group.id} role=\"group\" aria-label={group.name}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'baseline', mb: 1 }}>\n <Typography variant=\"subtitle1\" component=\"h3\">\n {group.name}\n </Typography>\n <Typography\n variant=\"caption\"\n color={count < group.min ? 'warning.main' : 'text.secondary'}\n >\n {rule}\n </Typography>\n </Stack>\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>\n {group.options.map((option) => {\n const selected = modifiers.some(\n (pick) => pick.groupId === group.id && pick.optionId === option.id,\n )\n return (\n <Chip\n key={option.id}\n label={\n // A choice priced by variant shows its price on this one (AGL-4100).\n CommerceModel.modifierOptionPriceCents(option, variant?.id)\n ? `${option.name} +${money(CommerceModel.modifierOptionPriceCents(option, variant?.id))}`\n : option.name\n }\n color={selected ? 'primary' : 'default'}\n variant={selected ? 'filled' : 'outlined'}\n aria-pressed={selected}\n onClick={() => toggle(group, option.id)}\n disabled={!selected && group.max > 1 && count >= group.max}\n sx={{ minHeight: POS_TOUCH_PX, px: 1 }}\n />\n )\n })}\n </Box>\n </Box>\n )\n })}\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle1\" component=\"h3\" sx={{ flex: 1 }}>\n {'Quantity'}\n </Typography>\n <IconButton\n aria-label=\"One fewer\"\n onClick={() => setQuantity((value) => Math.max(1, value - 1))}\n sx={{ width: POS_TOUCH_PX, height: POS_TOUCH_PX, border: 1, borderColor: 'divider' }}\n >\n {'−'}\n </IconButton>\n <TextField\n value={quantity}\n onChange={(event) => {\n const next = Math.round(Number(event.target.value.replace(/\\D/g, '')))\n setQuantity(Math.max(1, Math.min(maxQuantity, next || 1)))\n }}\n sx={{ width: 72 }}\n slotProps={{\n htmlInput: { inputMode: 'numeric', 'aria-label': 'Quantity', style: { textAlign: 'center' } },\n }}\n />\n <IconButton\n aria-label=\"One more\"\n onClick={() => setQuantity((value) => Math.min(maxQuantity, value + 1))}\n sx={{ width: POS_TOUCH_PX, height: POS_TOUCH_PX, border: 1, borderColor: 'divider' }}\n >\n {'+'}\n </IconButton>\n </Stack>\n </Stack>\n </DialogContent>\n <DialogActions sx={{ p: 2, gap: 1 }}>\n {props.onRemove ? (\n <Button color=\"error\" onClick={props.onRemove} sx={{ minHeight: POS_TOUCH_PX, mr: 'auto' }}>\n {'Remove'}\n </Button>\n ) : null}\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={!canAdd}\n onClick={() => {\n if (!variant || !chosen.ok) return\n props.onConfirm({ variant, modifiers, quantity })\n }}\n sx={{ minHeight: POS_TOUCH_PX, minWidth: 160 }}\n >\n {missing\n ? `Choose ${missing.name.toLowerCase()}`\n : `${props.onRemove ? 'Update' : 'Add'} · ${money(unitCents * quantity)}`}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nPosItemDialog.displayName = 'PosItemDialog'\n"],"names":["Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","IconButton","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useMediaQuery","useTheme","useEffect","useMemo","useState","CommerceModel","usd","POS_TOUCH_PX","posItemNeedsChoice","product","variants","length","productModifierGroups","variantFor","picked","find","variant","options","every","option","name","variantLabel","Object","values","join","soldOut","inventory","PosItemDialog","props","initial","money","formatMoney","maxQuantity","theme","phone","breakpoints","down","groups","setPicked","variantId","setVariantId","modifiers","setModifiers","quantity","setQuantity","start","id","item","chosen","resolveLineModifiers","unitCents","Math","round","Number","priceUsd","ok","extraCents","missing","group","filter","pick","groupId","min","canAdd","Boolean","blockSoldOut","toggle","optionId","current","inGroup","has","some","max","open","onClose","fullScreen","fullWidth","maxWidth","dividers","spacing","map","role","aria-label","component","sx","mb","exclusive","value","onChange","_event","flexWrap","gap","minHeight","minWidth","color","count","rule","modifierGroupRequired","direction","alignItems","display","selected","label","modifierOptionPriceCents","aria-pressed","onClick","disabled","px","flex","width","height","border","borderColor","event","next","target","replace","slotProps","htmlInput","inputMode","style","textAlign","p","onRemove","mr","onConfirm","toLowerCase","displayName"],"mappings":"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"}
|
|
@@ -83,7 +83,8 @@ import { useKioskIdle } from "./pos-kiosk/use-kiosk-idle.js";
|
|
|
83
83
|
}, label ? {
|
|
84
84
|
label
|
|
85
85
|
} : {}, {
|
|
86
|
-
|
|
86
|
+
// A choice priced by variant adds its price on this one (AGL-4100).
|
|
87
|
+
unitCents: variant.priceCents + picked.reduce((sum, option)=>sum + CommerceModel.modifierOptionPriceCents(option, variant.id), 0)
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-kiosk-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 type { ConsolePublicPageProps } from '@aglyn/aglyn'\nimport Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport CircularProgress from '@mui/material/CircularProgress'\nimport Container from '@mui/material/Container'\nimport Dialog from '@mui/material/Dialog'\nimport DialogActions from '@mui/material/DialogActions'\nimport DialogContent from '@mui/material/DialogContent'\nimport DialogContentText from '@mui/material/DialogContentText'\nimport DialogTitle from '@mui/material/DialogTitle'\nimport Stack from '@mui/material/Stack'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport * as CommerceModel from '../../model'\nimport { newAttemptKey, posNativeBridge } from './pos/pos-api'\nimport { PosItemDialog, posItemNeedsChoice, type PosItemChoice } from './pos/pos-item-dialog.component'\nimport { PosDisplayBrandMark, PosDisplayBrandScreen } from './pos-display/brand-screen'\nimport { PosDisplayPairingScreen } from './pos-display/pairing-screen'\nimport { displayMoney, type PosDisplayAnswer } from './pos-display/pos-display-api'\nimport { PosDisplayReceiptScreen } from './pos-display/receipt-screen'\nimport { PosDisplayTipScreen, posDisplayTouchSx } from './pos-display/tip-screen'\nimport { KioskDone, KioskPaying, KioskReview, type KioskPayOptions } from './pos-kiosk/kiosk-checkout'\nimport { KioskMenu, type KioskCartLine } from './pos-kiosk/kiosk-menu'\nimport { KioskStaffControl } from './pos-kiosk/kiosk-staff'\nimport {\n clearKioskCustomerStorage,\n kioskApi,\n readKioskToken,\n storeKioskToken,\n} from './pos-kiosk/pos-kiosk-api'\nimport { useKioskIdle } from './pos-kiosk/use-kiosk-idle'\n\n/** How often the kiosk asks after a card payment in flight. */\nexport const POS_KIOSK_PAYMENT_POLL_MS = 1_500\n\ntype Phase =\n | { kind: 'start' }\n | { kind: 'menu' }\n | { kind: 'review' }\n | { kind: 'tip'; method: 'reader' | 'tap' }\n | { kind: 'paying'; method: 'reader' | 'tap'; paymentId: string | null; chargeCents: number; failure: string | null }\n | { kind: 'receipt' }\n | { kind: 'done' }\n\ntype TipAnswer = { tipChoice: 'percent' | 'custom' | 'none'; tipPercent?: number; tipCents?: number }\n\n/** A product as the register's item sheet takes it, from the kiosk's catalog. */\nexport function kioskItemProduct(product: CommerceModel.PosKioskProduct) {\n return {\n $id: product.id,\n name: product.name,\n slug: product.id,\n type: 'physical',\n status: 'active',\n options: product.options,\n modifierGroups: product.modifierGroups,\n variants: product.variants.map((variant) => ({\n id: variant.id,\n options: variant.options,\n priceUsd: variant.priceCents / 100,\n // A sold-out variant reads as zero on hand; anything else as untracked,\n // so the kiosk never learns or shows a stock count.\n inventory: variant.soldOut ? 0 : null,\n })),\n } as unknown as CommerceModel.HostProduct & { $id: string }\n}\n\n/** The cart line a choice makes: same item and choices merge. */\nexport function kioskCartLine(\n product: CommerceModel.PosKioskProduct,\n choice: PosItemChoice,\n): KioskCartLine {\n const variant = product.variants.find((candidate) => candidate.id === choice.variant.id) ?? product.variants[0]!\n const picked = choice.modifiers\n .map((pick) => {\n const group = product.modifierGroups.find((candidate) => candidate.id === pick.groupId)\n return group?.options.find((option) => option.id === pick.optionId)\n })\n .filter((option): option is CommerceModel.ProductModifierOption => Boolean(option))\n const label = CommerceModel.lineLabelWithModifiers(\n Object.keys(variant.options).length ? Object.values(variant.options).join(' / ') : undefined,\n picked,\n )\n return {\n key: `${product.id}:${variant.id}:${CommerceModel.modifierSelectionKey(choice.modifiers)}`,\n productId: product.id,\n ...(variant.id !== 'default' || product.variants.length > 1 ? { variantId: variant.id } : {}),\n quantity: Math.min(CommerceModel.POS_KIOSK_MAX_QUANTITY, choice.quantity),\n ...(choice.modifiers.length ? { modifiers: choice.modifiers } : {}),\n name: product.name,\n ...(label ? { label } : {}),\n unitCents: variant.priceCents + picked.reduce((sum, option) => sum + option.priceCents, 0),\n }\n}\n\n/**\n * The self-service kiosk (AGL-3623), served at `/kiosk/commerce/pos-kiosk`\n * with no staff session: a customer builds their own order and pays on the\n * register's card reader or Tap to Pay, or sends it to the counter.\n *\n * It holds one secret — the kiosk token from pairing — and everything the\n * customer chooses or types lives in this component's memory only. The idle\n * reset (and \"Done\", and \"Start over\") voids an unpaid order, drops the\n * cart, the tip and any email or phone, sweeps the kiosk's storage keys, and\n * remounts every screen, so the next customer finds nothing of the last.\n */\nexport default function PosKioskPage(_props: ConsolePublicPageProps) {\n const [token, setToken] = useState<string | null | undefined>(undefined)\n const [context, setContext] = useState<CommerceModel.PosKioskContext | null>(null)\n const [catalog, setCatalog] = useState<CommerceModel.PosKioskCatalog | null>(null)\n const [catalogLoading, setCatalogLoading] = useState(false)\n const [categoryId, setCategoryId] = useState<string | null>(null)\n const [phase, setPhase] = useState<Phase>({ kind: 'start' })\n const [lines, setLines] = useState<KioskCartLine[]>([])\n const [itemProduct, setItemProduct] = useState<CommerceModel.PosKioskProduct | null>(null)\n const [cartOpen, setCartOpen] = useState(false)\n const [sale, setSale] = useState<CommerceModel.PosKioskSale | null>(null)\n const [tip, setTip] = useState<TipAnswer>({ tipChoice: 'none' })\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n const [offline, setOffline] = useState(false)\n // Bumped by every reset: keys every screen, so inputs never carry over.\n const [turn, setTurn] = useState(0)\n // One attempt per cart, and one per press of a payment button.\n const checkoutKey = useRef<string | null>(null)\n const payKey = useRef<string | null>(null)\n const saleRef = useRef(sale)\n saleRef.current = sale\n const phaseRef = useRef(phase)\n phaseRef.current = phase\n\n useEffect(() => {\n setToken(readKioskToken())\n }, [])\n\n const unpaired = useCallback(() => {\n storeKioskToken(null)\n clearKioskCustomerStorage()\n setToken(null)\n setContext(null)\n setCatalog(null)\n setSale(null)\n setLines([])\n setPhase({ kind: 'start' })\n }, [])\n\n /** A response that says the kiosk is no longer paired ends the session. */\n const lost = useCallback(\n (status: number) => {\n if (status === 401) {\n unpaired()\n return true\n }\n return false\n },\n [unpaired],\n )\n\n // The kiosk's settings and the menu: read when paired, and again every\n // ten minutes while idle on the start screen, so an edit reaches it.\n const refresh = useCallback(async () => {\n if (!token) return\n const result = await kioskApi.context(token)\n if (lost(result.status)) return\n setOffline(!result.ok && result.status === 0)\n if (result.ok && result.value) setContext(result.value)\n }, [token, lost])\n\n useEffect(() => {\n void refresh()\n const timer = setInterval(() => {\n if (phaseRef.current.kind === 'start') void refresh()\n }, 10 * 60 * 1000)\n return () => clearInterval(timer)\n }, [refresh])\n\n useEffect(() => {\n if (!token) return undefined\n let active = true\n setCatalogLoading(true)\n void kioskApi.catalog(token, categoryId).then((result) => {\n if (!active) return\n setCatalogLoading(false)\n if (lost(result.status)) return\n if (result.ok && result.value) setCatalog(result.value)\n else setOffline(result.status === 0)\n })\n return () => {\n active = false\n }\n }, [token, categoryId, turn, lost])\n\n const currency = context?.currency ?? catalog?.currency ?? 'usd'\n const money = useCallback((cents: number) => displayMoney(cents, currency), [currency])\n\n /**\n * THE RESET: the unpaid order voided, every customer detail dropped from\n * memory and storage, and the screens remounted on the start screen.\n */\n const reset = useCallback(() => {\n const open = saleRef.current\n if (token && open && open.status === 'open') void kioskApi.abandon(token, open.orderId)\n setSale(null)\n setLines([])\n setTip({ tipChoice: 'none' })\n setItemProduct(null)\n setCartOpen(false)\n setNotice(null)\n setCategoryId(null)\n checkoutKey.current = null\n payKey.current = null\n clearKioskCustomerStorage()\n setPhase({ kind: 'start' })\n setTurn((value) => value + 1)\n }, [token])\n\n const idle = useKioskIdle({\n // Never while a card is being collected: the customer is at the reader.\n active: Boolean(token) && phase.kind !== 'start' && phase.kind !== 'paying',\n idleSeconds: context?.idleSeconds ?? CommerceModel.POS_KIOSK_IDLE_SECONDS_DEFAULT,\n warningSeconds: CommerceModel.POS_KIOSK_IDLE_WARNING_SECONDS,\n onExpire: reset,\n })\n\n // The order-number screen returns to the start on its own.\n useEffect(() => {\n if (phase.kind !== 'done') return undefined\n const timer = setTimeout(reset, CommerceModel.POS_KIOSK_DONE_SECONDS * 1000)\n return () => clearTimeout(timer)\n }, [phase.kind, reset])\n\n const addChoice = useCallback((product: CommerceModel.PosKioskProduct, choice: PosItemChoice) => {\n const line = kioskCartLine(product, choice)\n checkoutKey.current = null\n setLines((current) => {\n const existing = current.find((candidate) => candidate.key === line.key)\n if (existing) {\n return current.map((candidate) =>\n candidate.key === line.key\n ? { ...candidate, quantity: Math.min(CommerceModel.POS_KIOSK_MAX_QUANTITY, candidate.quantity + line.quantity) }\n : candidate,\n )\n }\n if (current.length >= CommerceModel.POS_KIOSK_MAX_LINES) return current\n return [...current, line]\n })\n }, [])\n\n const tapProduct = useCallback(\n (product: CommerceModel.PosKioskProduct) => {\n const asItem = kioskItemProduct(product)\n if (posItemNeedsChoice(asItem)) {\n setItemProduct(product)\n return\n }\n const variant = asItem.variants[0]\n if (!variant || product.variants[0]?.soldOut) return\n addChoice(product, { variant, modifiers: [], quantity: 1 })\n },\n [addChoice],\n )\n\n const checkout = useCallback(async () => {\n if (!token || busy || lines.length === 0) return\n if (!checkoutKey.current) checkoutKey.current = newAttemptKey()\n setBusy(true)\n setNotice(null)\n const result = await kioskApi.checkout(\n token,\n lines.map(({ productId, variantId, quantity, modifiers }) => ({\n productId,\n ...(variantId ? { variantId } : {}),\n quantity,\n ...(modifiers ? { modifiers } : {}),\n })),\n checkoutKey.current,\n )\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok || !result.value?.sale) {\n // A refused cart is changed before it is tried again.\n checkoutKey.current = null\n setNotice(result.error ?? 'Your order could not be priced. Try again.')\n return\n }\n setSale(result.value.sale)\n setCartOpen(false)\n setPhase({ kind: 'review' })\n }, [token, busy, lines, lost])\n\n const backToMenu = useCallback(() => {\n const open = saleRef.current\n if (token && open && open.status === 'open') void kioskApi.abandon(token, open.orderId)\n setSale(null)\n checkoutKey.current = null\n setNotice(null)\n setPhase({ kind: 'menu' })\n }, [token])\n\n const sendToCounter = useCallback(async () => {\n const open = saleRef.current\n if (!token || !open) return\n setBusy(true)\n const result = await kioskApi.counter(token, open.orderId)\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok || !result.value?.sale) {\n setNotice(result.error ?? 'Your order could not be sent to the counter.')\n return\n }\n setSale(result.value.sale)\n setLines([])\n setPhase({ kind: 'done' })\n }, [token, lost])\n\n const startPayment = useCallback(\n async (method: 'reader' | 'tap', answer: TipAnswer) => {\n const open = saleRef.current\n if (!token || !open) return\n if (!payKey.current) payKey.current = newAttemptKey()\n setBusy(true)\n setNotice(null)\n const result = await kioskApi.pay(token, { orderId: open.orderId, method, ...answer }, payKey.current)\n if (lost(result.status)) return setBusy(false)\n if (!result.ok || !result.value) {\n setBusy(false)\n payKey.current = null\n setNotice(result.error ?? 'The card payment could not be started.')\n setPhase({ kind: 'review' })\n return\n }\n const { sale: next, paymentId, clientSecret, paymentIntentId } = result.value\n setSale(next)\n const tipCents = CommerceModel.posKioskTipCents(answer.tipChoice, {\n baseCents: open.dueCents,\n enabled: true,\n percentages: context?.tipping.percentages ?? [],\n percent: answer.tipPercent,\n cents: answer.tipCents,\n })\n const chargeCents = open.dueCents + (tipCents ?? 0)\n setPhase({ kind: 'paying', method, paymentId: paymentId ?? null, chargeCents, failure: null })\n setBusy(false)\n if (method === 'tap') {\n const bridge = posNativeBridge()\n if (!bridge || !clientSecret || !paymentIntentId) {\n setPhase({ kind: 'paying', method, paymentId: paymentId ?? null, chargeCents, failure: 'Tap to Pay is not available on this device.' })\n return\n }\n const collected = await bridge\n .collectCardPayment({ paymentIntentId, clientSecret, amountCents: chargeCents })\n .catch(() => ({ status: 'failed' as const, message: undefined }))\n if (collected.status !== 'collected') {\n setPhase({\n kind: 'paying',\n method,\n paymentId: paymentId ?? null,\n chargeCents,\n failure: collected.status === 'canceled' ? 'The payment was canceled.' : (collected.message ?? 'The card was not read.'),\n })\n }\n }\n },\n [token, lost, context],\n )\n\n // The card in flight, asked after until it is paid or it fails.\n const paymentId = phase.kind === 'paying' ? phase.paymentId : null\n const paymentFailed = phase.kind === 'paying' ? Boolean(phase.failure) : false\n useEffect(() => {\n if (!token || !paymentId || paymentFailed) return undefined\n const open = saleRef.current\n if (!open) return undefined\n let active = true\n const timer = setInterval(async () => {\n const result = await kioskApi.paymentStatus(token, open.orderId, paymentId)\n if (!active) return\n if (lost(result.status)) return\n const next = result.value?.sale\n if (!next) return\n setSale(next)\n if (next.status === 'paid') {\n clearInterval(timer)\n setLines([])\n payKey.current = null\n setPhase({ kind: 'receipt' })\n return\n }\n const status = next.payment?.id === paymentId ? next.payment.status : ''\n if (status === 'failed' || status === 'canceled') {\n clearInterval(timer)\n payKey.current = null\n setPhase((current) =>\n current.kind === 'paying'\n ? { ...current, failure: next.payment?.failureMessage ?? 'The card was declined.' }\n : current,\n )\n }\n }, POS_KIOSK_PAYMENT_POLL_MS)\n return () => {\n active = false\n clearInterval(timer)\n }\n }, [token, paymentId, paymentFailed, lost])\n\n const cancelPayment = useCallback(async () => {\n const open = saleRef.current\n if (!token || !open || phase.kind !== 'paying') return\n setBusy(true)\n if (phase.paymentId && !phase.failure) await kioskApi.cancelPayment(token, open.orderId, phase.paymentId)\n const fresh = await kioskApi.sale(token, open.orderId)\n setBusy(false)\n payKey.current = null\n if (fresh.value?.sale) setSale(fresh.value.sale)\n if (fresh.value?.sale.status === 'paid') {\n setPhase({ kind: 'receipt' })\n return\n }\n setPhase({ kind: 'review' })\n }, [token, phase])\n\n const answerReceipt = useCallback(\n async (answer: PosDisplayAnswer) => {\n const paid = saleRef.current\n if (!token || !paid || !answer.receiptChannel) return\n setBusy(true)\n const result = await kioskApi.receipt(token, {\n orderId: paid.orderId,\n channel: answer.receiptChannel,\n ...(answer.email ? { to: answer.email } : {}),\n ...(answer.phone ? { to: answer.phone } : {}),\n ...(answer.marketingOptIn ? { marketingOptIn: true } : {}),\n })\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok) {\n setNotice(result.error ?? 'Your receipt could not be sent. Ask at the counter.')\n }\n setPhase({ kind: 'done' })\n },\n [token, lost],\n )\n\n const pay: KioskPayOptions = useMemo(\n () => ({\n reader: Boolean(context?.payments.cardPresent && context.payments.reader),\n tap: Boolean(context?.payments.cardPresent && posNativeBridge()),\n counter: Boolean(context?.payments.payAtCounter),\n }),\n [context],\n )\n\n const choosePay = useCallback(\n (method: 'reader' | 'tap') => {\n if (context?.tipping.enabled) {\n setPhase({ kind: 'tip', method })\n return\n }\n setTip({ tipChoice: 'none' })\n void startPayment(method, { tipChoice: 'none' })\n },\n [context, startPayment],\n )\n\n if (token === undefined) {\n return (\n <Box sx={{ minHeight: '100dvh', display: 'grid', placeItems: 'center' }}>\n <CircularProgress aria-label=\"Loading\" />\n </Box>\n )\n }\n\n if (!token) {\n return (\n <PosDisplayPairingScreen\n mode=\"kiosk\"\n onPaired={(next) => {\n storeKioskToken(next)\n setToken(next)\n }}\n />\n )\n }\n\n const branding = context?.branding ?? null\n let screen\n if (phase.kind === 'start') {\n screen = (\n <PosDisplayBrandScreen branding={branding} message={branding?.message || 'Order here'}>\n <Button\n variant=\"contained\"\n size=\"large\"\n onClick={() => setPhase({ kind: 'menu' })}\n sx={(theme) => ({ ...posDisplayTouchSx(theme), px: 6 })}\n >\n {'Start order'}\n </Button>\n </PosDisplayBrandScreen>\n )\n } else if (phase.kind === 'menu') {\n screen = (\n <>\n {notice ? (\n <Alert severity=\"warning\" onClose={() => setNotice(null)} sx={{ m: 2, mb: 0 }}>\n {notice}\n </Alert>\n ) : null}\n <KioskMenu\n catalog={catalog}\n loading={catalogLoading && !catalog}\n categoryId={categoryId}\n onCategory={setCategoryId}\n onProduct={tapProduct}\n lines={lines}\n currency={currency}\n onReview={() => void checkout()}\n onQuantity={(key, quantity) => {\n checkoutKey.current = null\n setLines((current) =>\n quantity <= 0\n ? current.filter((line) => line.key !== key)\n : current.map((line) => (line.key === key ? { ...line, quantity } : line)),\n )\n }}\n cartOpen={cartOpen}\n onCartOpen={setCartOpen}\n busy={busy}\n />\n </>\n )\n } else if (phase.kind === 'review' && sale) {\n screen = (\n <KioskReview\n sale={sale}\n currency={currency}\n pay={pay}\n busy={busy}\n notice={notice}\n onPay={choosePay}\n onCounter={() => void sendToCounter()}\n onBack={backToMenu}\n />\n )\n } else if (phase.kind === 'tip' && sale && context) {\n screen = (\n <Container maxWidth=\"md\" sx={{ py: 4 }}>\n <Stack spacing={4} sx={{ alignItems: 'center' }}>\n <PosDisplayBrandMark branding={branding} />\n <PosDisplayTipScreen\n tip={{ baseCents: sale.dueCents, percentages: context.tipping.percentages, allowCustom: true }}\n promptId={`kiosk-${sale.orderId}`}\n busy={busy}\n currency={currency}\n onAnswer={(answer) => {\n const next: TipAnswer = {\n tipChoice: answer.tipChoice ?? 'none',\n ...(answer.tipPercent ? { tipPercent: answer.tipPercent } : {}),\n ...(answer.tipChoice === 'custom' ? { tipCents: answer.tipCents ?? 0 } : {}),\n }\n setTip(next)\n void startPayment(phase.method, next)\n }}\n />\n <Button onClick={() => setPhase({ kind: 'review' })} disabled={busy}>\n {'Back'}\n </Button>\n </Stack>\n </Container>\n )\n } else if (phase.kind === 'paying' && sale) {\n screen = (\n <KioskPaying\n chargeCents={phase.chargeCents}\n currency={currency}\n method={phase.method}\n failure={phase.failure}\n testMode={Boolean(context?.testMode && phase.method === 'reader')}\n busy={busy}\n onCancel={() => void cancelPayment()}\n onRetry={() => void startPayment(phase.method, tip)}\n onCounter={pay.counter ? () => void sendToCounter() : null}\n onSimulate={\n phase.paymentId\n ? () => void kioskApi.simulate(token, sale.orderId, phase.paymentId as string)\n : null\n }\n />\n )\n } else if (phase.kind === 'receipt' && sale && context) {\n screen = (\n <Container maxWidth=\"md\" sx={{ py: 4 }}>\n <Stack spacing={4} sx={{ alignItems: 'center' }}>\n <PosDisplayBrandMark branding={branding} />\n <PosDisplayReceiptScreen\n receipt={{ channels: context.receipts, offerMarketing: context.offerMarketing }}\n promptId={`kiosk-${sale.orderId}`}\n busy={busy}\n onAnswer={(answer) => void answerReceipt(answer)}\n />\n </Stack>\n </Container>\n )\n } else if (phase.kind === 'done' && sale) {\n screen = <KioskDone sale={sale} currency={currency} onDone={reset} />\n } else {\n screen = <PosDisplayBrandScreen branding={branding} busy />\n }\n\n return (\n <Box key={turn} sx={{ position: 'relative', minHeight: '100dvh' }}>\n {offline ? (\n <Alert severity=\"warning\" sx={{ position: 'fixed', top: 0, left: 0, right: 0, zIndex: (theme) => theme.zIndex.modal + 1 }}>\n {'Reconnecting…'}\n </Alert>\n ) : null}\n {screen}\n <PosItemDialog\n product={itemProduct ? kioskItemProduct(itemProduct) : null}\n onClose={() => setItemProduct(null)}\n onConfirm={(choice) => {\n const product = itemProduct\n setItemProduct(null)\n if (product) addChoice(product, choice)\n }}\n formatMoney={money}\n blockSoldOut\n maxQuantity={CommerceModel.POS_KIOSK_MAX_QUANTITY}\n />\n <Dialog open={idle.warning !== null} onClose={idle.stillHere} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Still there?'}</DialogTitle>\n <DialogContent>\n <DialogContentText>\n {`This order will be cleared in ${idle.warning ?? 0} seconds.`}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={reset}>{'Start over'}</Button>\n <Button variant=\"contained\" onClick={idle.stillHere}>\n {'I’m still here'}\n </Button>\n </DialogActions>\n </Dialog>\n {phase.kind === 'start' || phase.kind === 'menu' ? (\n <KioskStaffControl token={token} onExit={unpaired} onUnauthorized={unpaired} />\n ) : null}\n </Box>\n )\n}\n\nPosKioskPage.displayName = 'PosKioskPage'\n"],"names":["Alert","Box","Button","CircularProgress","Container","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Stack","useCallback","useEffect","useMemo","useRef","useState","CommerceModel","newAttemptKey","posNativeBridge","PosItemDialog","posItemNeedsChoice","PosDisplayBrandMark","PosDisplayBrandScreen","PosDisplayPairingScreen","displayMoney","PosDisplayReceiptScreen","PosDisplayTipScreen","posDisplayTouchSx","KioskDone","KioskPaying","KioskReview","KioskMenu","KioskStaffControl","clearKioskCustomerStorage","kioskApi","readKioskToken","storeKioskToken","useKioskIdle","POS_KIOSK_PAYMENT_POLL_MS","kioskItemProduct","product","$id","id","name","slug","type","status","options","modifierGroups","variants","map","variant","priceUsd","priceCents","inventory","soldOut","kioskCartLine","choice","find","candidate","picked","modifiers","pick","group","groupId","option","optionId","filter","Boolean","label","lineLabelWithModifiers","Object","keys","length","values","join","undefined","key","modifierSelectionKey","productId","variantId","quantity","Math","min","POS_KIOSK_MAX_QUANTITY","unitCents","reduce","sum","PosKioskPage","_props","context","idle","token","setToken","setContext","catalog","setCatalog","catalogLoading","setCatalogLoading","categoryId","setCategoryId","phase","setPhase","kind","lines","setLines","itemProduct","setItemProduct","cartOpen","setCartOpen","sale","setSale","tip","setTip","tipChoice","busy","setBusy","notice","setNotice","offline","setOffline","turn","setTurn","checkoutKey","payKey","saleRef","current","phaseRef","unpaired","lost","refresh","result","ok","value","timer","setInterval","clearInterval","active","then","currency","money","cents","reset","open","abandon","orderId","idleSeconds","POS_KIOSK_IDLE_SECONDS_DEFAULT","warningSeconds","POS_KIOSK_IDLE_WARNING_SECONDS","onExpire","setTimeout","POS_KIOSK_DONE_SECONDS","clearTimeout","addChoice","line","existing","POS_KIOSK_MAX_LINES","tapProduct","asItem","checkout","error","backToMenu","sendToCounter","counter","startPayment","method","answer","pay","next","paymentId","clientSecret","paymentIntentId","tipCents","posKioskTipCents","baseCents","dueCents","enabled","percentages","tipping","percent","tipPercent","chargeCents","failure","bridge","collected","collectCardPayment","amountCents","catch","message","paymentFailed","paymentStatus","payment","failureMessage","cancelPayment","fresh","answerReceipt","paid","receiptChannel","receipt","channel","email","to","phone","marketingOptIn","reader","payments","cardPresent","tap","payAtCounter","choosePay","sx","minHeight","display","placeItems","aria-label","mode","onPaired","branding","screen","size","onClick","theme","px","severity","onClose","m","mb","loading","onCategory","onProduct","onReview","onQuantity","onCartOpen","onPay","onCounter","onBack","maxWidth","py","spacing","alignItems","allowCustom","promptId","onAnswer","disabled","testMode","onCancel","onRetry","onSimulate","simulate","channels","receipts","offerMarketing","onDone","position","top","left","right","zIndex","modal","onConfirm","formatMoney","blockSoldOut","maxQuantity","warning","stillHere","fullWidth","onExit","onUnauthorized","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAGA,OAAOA,WAAW,sBAAqB;AACvC,OAAOC,SAAS,oBAAmB;AACnC,OAAOC,YAAY,uBAAsB;AACzC,OAAOC,sBAAsB,iCAAgC;AAC7D,OAAOC,eAAe,0BAAyB;AAC/C,OAAOC,YAAY,uBAAsB;AACzC,OAAOC,mBAAmB,8BAA6B;AACvD,OAAOC,mBAAmB,8BAA6B;AACvD,OAAOC,uBAAuB,kCAAiC;AAC/D,OAAOC,iBAAiB,4BAA2B;AACnD,OAAOC,WAAW,sBAAqB;AACvC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AACzE,YAAYC,mBAAmB,uBAAa;AAC5C,SAASC,aAAa,EAAEC,eAAe,QAAQ,mBAAe;AAC9D,SAASC,aAAa,EAAEC,kBAAkB,QAA4B,qCAAiC;AACvG,SAASC,mBAAmB,EAAEC,qBAAqB,QAAQ,gCAA4B;AACvF,SAASC,uBAAuB,QAAQ,kCAA8B;AACtE,SAASC,YAAY,QAA+B,mCAA+B;AACnF,SAASC,uBAAuB,QAAQ,kCAA8B;AACtE,SAASC,mBAAmB,EAAEC,iBAAiB,QAAQ,8BAA0B;AACjF,SAASC,SAAS,EAAEC,WAAW,EAAEC,WAAW,QAA8B,gCAA4B;AACtG,SAASC,SAAS,QAA4B,4BAAwB;AACtE,SAASC,iBAAiB,QAAQ,6BAAyB;AAC3D,SACEC,yBAAyB,EACzBC,QAAQ,EACRC,cAAc,EACdC,eAAe,QACV,+BAA2B;AAClC,SAASC,YAAY,QAAQ,gCAA4B;AAEzD,6DAA6D,GAC7D,OAAO,MAAMC,4BAA4B,KAAK;AAa9C,+EAA+E,GAC/E,OAAO,SAASC,iBAAiBC,OAAsC;IACrE,OAAO;QACLC,KAAKD,QAAQE,EAAE;QACfC,MAAMH,QAAQG,IAAI;QAClBC,MAAMJ,QAAQE,EAAE;QAChBG,MAAM;QACNC,QAAQ;QACRC,SAASP,QAAQO,OAAO;QACxBC,gBAAgBR,QAAQQ,cAAc;QACtCC,UAAUT,QAAQS,QAAQ,CAACC,GAAG,CAAC,CAACC,UAAa,CAAA;gBAC3CT,IAAIS,QAAQT,EAAE;gBACdK,SAASI,QAAQJ,OAAO;gBACxBK,UAAUD,QAAQE,UAAU,GAAG;gBAC/B,wEAAwE;gBACxE,oDAAoD;gBACpDC,WAAWH,QAAQI,OAAO,GAAG,IAAI;YACnC,CAAA;IACF;AACF;AAEA,+DAA+D,GAC/D,OAAO,SAASC,cACdhB,OAAsC,EACtCiB,MAAqB;QAELjB;IAAhB,MAAMW,WAAUX,yBAAAA,QAAQS,QAAQ,CAACS,IAAI,CAAC,CAACC,YAAcA,UAAUjB,EAAE,KAAKe,OAAON,OAAO,CAACT,EAAE,aAAvEF,yBAA4EA,QAAQS,QAAQ,CAAC,EAAE;IAC/G,MAAMW,SAASH,OAAOI,SAAS,CAC5BX,GAAG,CAAC,CAACY;QACJ,MAAMC,QAAQvB,QAAQQ,cAAc,CAACU,IAAI,CAAC,CAACC,YAAcA,UAAUjB,EAAE,KAAKoB,KAAKE,OAAO;QACtF,OAAOD,yBAAAA,MAAOhB,OAAO,CAACW,IAAI,CAAC,CAACO,SAAWA,OAAOvB,EAAE,KAAKoB,KAAKI,QAAQ;IACpE,GACCC,MAAM,CAAC,CAACF,SAA0DG,QAAQH;IAC7E,MAAMI,QAAQrD,cAAcsD,sBAAsB,CAChDC,OAAOC,IAAI,CAACrB,QAAQJ,OAAO,EAAE0B,MAAM,GAAGF,OAAOG,MAAM,CAACvB,QAAQJ,OAAO,EAAE4B,IAAI,CAAC,SAASC,WACnFhB;IAEF,OAAO;QACLiB,KAAK,GAAGrC,QAAQE,EAAE,CAAC,CAAC,EAAES,QAAQT,EAAE,CAAC,CAAC,EAAE1B,cAAc8D,oBAAoB,CAACrB,OAAOI,SAAS,GAAG;QAC1FkB,WAAWvC,QAAQE,EAAE;OACjBS,QAAQT,EAAE,KAAK,aAAaF,QAAQS,QAAQ,CAACwB,MAAM,GAAG,IAAI;QAAEO,WAAW7B,QAAQT,EAAE;IAAC,IAAI,CAAC;QAC3FuC,UAAUC,KAAKC,GAAG,CAACnE,cAAcoE,sBAAsB,EAAE3B,OAAOwB,QAAQ;OACpExB,OAAOI,SAAS,CAACY,MAAM,GAAG;QAAEZ,WAAWJ,OAAOI,SAAS;IAAC,IAAI,CAAC;QACjElB,MAAMH,QAAQG,IAAI;OACd0B,QAAQ;QAAEA;IAAM,IAAI,CAAC;QACzBgB,WAAWlC,QAAQE,UAAU,GAAGO,OAAO0B,MAAM,CAAC,CAACC,KAAKtB,SAAWsB,MAAMtB,OAAOZ,UAAU,EAAE;;AAE5F;AAEA;;;;;;;;;;CAUC,GACD,eAAe,SAASmC,aAAaC,MAA8B;QAsFhDC,2BAwb2BC;IA7gB5C,MAAM,CAACC,OAAOC,SAAS,GAAG9E,SAAoC6D;IAC9D,MAAM,CAACc,SAASI,WAAW,GAAG/E,SAA+C;IAC7E,MAAM,CAACgF,SAASC,WAAW,GAAGjF,SAA+C;IAC7E,MAAM,CAACkF,gBAAgBC,kBAAkB,GAAGnF,SAAS;IACrD,MAAM,CAACoF,YAAYC,cAAc,GAAGrF,SAAwB;IAC5D,MAAM,CAACsF,OAAOC,SAAS,GAAGvF,SAAgB;QAAEwF,MAAM;IAAQ;IAC1D,MAAM,CAACC,OAAOC,SAAS,GAAG1F,SAA0B,EAAE;IACtD,MAAM,CAAC2F,aAAaC,eAAe,GAAG5F,SAA+C;IACrF,MAAM,CAAC6F,UAAUC,YAAY,GAAG9F,SAAS;IACzC,MAAM,CAAC+F,MAAMC,QAAQ,GAAGhG,SAA4C;IACpE,MAAM,CAACiG,KAAKC,OAAO,GAAGlG,SAAoB;QAAEmG,WAAW;IAAO;IAC9D,MAAM,CAACC,MAAMC,QAAQ,GAAGrG,SAAS;IACjC,MAAM,CAACsG,QAAQC,UAAU,GAAGvG,SAAwB;IACpD,MAAM,CAACwG,SAASC,WAAW,GAAGzG,SAAS;IACvC,wEAAwE;IACxE,MAAM,CAAC0G,MAAMC,QAAQ,GAAG3G,SAAS;IACjC,+DAA+D;IAC/D,MAAM4G,cAAc7G,OAAsB;IAC1C,MAAM8G,SAAS9G,OAAsB;IACrC,MAAM+G,UAAU/G,OAAOgG;IACvBe,QAAQC,OAAO,GAAGhB;IAClB,MAAMiB,WAAWjH,OAAOuF;IACxB0B,SAASD,OAAO,GAAGzB;IAEnBzF,UAAU;QACRiF,SAAS1D;IACX,GAAG,EAAE;IAEL,MAAM6F,WAAWrH,YAAY;QAC3ByB,gBAAgB;QAChBH;QACA4D,SAAS;QACTC,WAAW;QACXE,WAAW;QACXe,QAAQ;QACRN,SAAS,EAAE;QACXH,SAAS;YAAEC,MAAM;QAAQ;IAC3B,GAAG,EAAE;IAEL,yEAAyE,GACzE,MAAM0B,OAAOtH,YACX,CAACmC;QACC,IAAIA,WAAW,KAAK;YAClBkF;YACA,OAAO;QACT;QACA,OAAO;IACT,GACA;QAACA;KAAS;IAGZ,uEAAuE;IACvE,qEAAqE;IACrE,MAAME,UAAUvH,YAAY;QAC1B,IAAI,CAACiF,OAAO;QACZ,MAAMuC,SAAS,MAAMjG,SAASwD,OAAO,CAACE;QACtC,IAAIqC,KAAKE,OAAOrF,MAAM,GAAG;QACzB0E,WAAW,CAACW,OAAOC,EAAE,IAAID,OAAOrF,MAAM,KAAK;QAC3C,IAAIqF,OAAOC,EAAE,IAAID,OAAOE,KAAK,EAAEvC,WAAWqC,OAAOE,KAAK;IACxD,GAAG;QAACzC;QAAOqC;KAAK;IAEhBrH,UAAU;QACR,KAAKsH;QACL,MAAMI,QAAQC,YAAY;YACxB,IAAIR,SAASD,OAAO,CAACvB,IAAI,KAAK,SAAS,KAAK2B;QAC9C,GAAG,KAAK,KAAK;QACb,OAAO,IAAMM,cAAcF;IAC7B,GAAG;QAACJ;KAAQ;IAEZtH,UAAU;QACR,IAAI,CAACgF,OAAO,OAAOhB;QACnB,IAAI6D,SAAS;QACbvC,kBAAkB;QAClB,KAAKhE,SAAS6D,OAAO,CAACH,OAAOO,YAAYuC,IAAI,CAAC,CAACP;YAC7C,IAAI,CAACM,QAAQ;YACbvC,kBAAkB;YAClB,IAAI+B,KAAKE,OAAOrF,MAAM,GAAG;YACzB,IAAIqF,OAAOC,EAAE,IAAID,OAAOE,KAAK,EAAErC,WAAWmC,OAAOE,KAAK;iBACjDb,WAAWW,OAAOrF,MAAM,KAAK;QACpC;QACA,OAAO;YACL2F,SAAS;QACX;IACF,GAAG;QAAC7C;QAAOO;QAAYsB;QAAMQ;KAAK;IAElC,MAAMU,YAAWjD,gBAAAA,2BAAAA,QAASiD,QAAQ,oBAAI5C,2BAAAA,QAAS4C,QAAQ,YAAtCjD,OAA0C;IAC3D,MAAMkD,QAAQjI,YAAY,CAACkI,QAAkBrH,aAAaqH,OAAOF,WAAW;QAACA;KAAS;IAEtF;;;GAGC,GACD,MAAMG,QAAQnI,YAAY;QACxB,MAAMoI,OAAOlB,QAAQC,OAAO;QAC5B,IAAIlC,SAASmD,QAAQA,KAAKjG,MAAM,KAAK,QAAQ,KAAKZ,SAAS8G,OAAO,CAACpD,OAAOmD,KAAKE,OAAO;QACtFlC,QAAQ;QACRN,SAAS,EAAE;QACXQ,OAAO;YAAEC,WAAW;QAAO;QAC3BP,eAAe;QACfE,YAAY;QACZS,UAAU;QACVlB,cAAc;QACduB,YAAYG,OAAO,GAAG;QACtBF,OAAOE,OAAO,GAAG;QACjB7F;QACAqE,SAAS;YAAEC,MAAM;QAAQ;QACzBmB,QAAQ,CAACW,QAAUA,QAAQ;IAC7B,GAAG;QAACzC;KAAM;IAEV,MAAMD,OAAOtD,aAAa;QACxB,wEAAwE;QACxEoG,QAAQrE,QAAQwB,UAAUS,MAAME,IAAI,KAAK,WAAWF,MAAME,IAAI,KAAK;QACnE2C,WAAW,WAAExD,2BAAAA,QAASwD,WAAW,oBAAIlI,cAAcmI,8BAA8B;QACjFC,gBAAgBpI,cAAcqI,8BAA8B;QAC5DC,UAAUR;IACZ;IAEA,2DAA2D;IAC3DlI,UAAU;QACR,IAAIyF,MAAME,IAAI,KAAK,QAAQ,OAAO3B;QAClC,MAAM0D,QAAQiB,WAAWT,OAAO9H,cAAcwI,sBAAsB,GAAG;QACvE,OAAO,IAAMC,aAAanB;IAC5B,GAAG;QAACjC,MAAME,IAAI;QAAEuC;KAAM;IAEtB,MAAMY,YAAY/I,YAAY,CAAC6B,SAAwCiB;QACrE,MAAMkG,OAAOnG,cAAchB,SAASiB;QACpCkE,YAAYG,OAAO,GAAG;QACtBrB,SAAS,CAACqB;YACR,MAAM8B,WAAW9B,QAAQpE,IAAI,CAAC,CAACC,YAAcA,UAAUkB,GAAG,KAAK8E,KAAK9E,GAAG;YACvE,IAAI+E,UAAU;gBACZ,OAAO9B,QAAQ5E,GAAG,CAAC,CAACS,YAClBA,UAAUkB,GAAG,KAAK8E,KAAK9E,GAAG,GACtB,aAAKlB;wBAAWsB,UAAUC,KAAKC,GAAG,CAACnE,cAAcoE,sBAAsB,EAAEzB,UAAUsB,QAAQ,GAAG0E,KAAK1E,QAAQ;yBAC3GtB;YAER;YACA,IAAImE,QAAQrD,MAAM,IAAIzD,cAAc6I,mBAAmB,EAAE,OAAO/B;YAChE,OAAO;mBAAIA;gBAAS6B;aAAK;QAC3B;IACF,GAAG,EAAE;IAEL,MAAMG,aAAanJ,YACjB,CAAC6B;YAOiBA;QANhB,MAAMuH,SAASxH,iBAAiBC;QAChC,IAAIpB,mBAAmB2I,SAAS;YAC9BpD,eAAenE;YACf;QACF;QACA,MAAMW,UAAU4G,OAAO9G,QAAQ,CAAC,EAAE;QAClC,IAAI,CAACE,aAAWX,qBAAAA,QAAQS,QAAQ,CAAC,EAAE,qBAAnBT,mBAAqBe,OAAO,GAAE;QAC9CmG,UAAUlH,SAAS;YAAEW;YAASU,WAAW,EAAE;YAAEoB,UAAU;QAAE;IAC3D,GACA;QAACyE;KAAU;IAGb,MAAMM,WAAWrJ,YAAY;YAiBRwH;QAhBnB,IAAI,CAACvC,SAASuB,QAAQX,MAAM/B,MAAM,KAAK,GAAG;QAC1C,IAAI,CAACkD,YAAYG,OAAO,EAAEH,YAAYG,OAAO,GAAG7G;QAChDmG,QAAQ;QACRE,UAAU;QACV,MAAMa,SAAS,MAAMjG,SAAS8H,QAAQ,CACpCpE,OACAY,MAAMtD,GAAG,CAAC,CAAC,EAAE6B,SAAS,EAAEC,SAAS,EAAEC,QAAQ,EAAEpB,SAAS,EAAE,GAAM;gBAC5DkB;eACIC,YAAY;gBAAEA;YAAU,IAAI,CAAC;gBACjCC;eACIpB,YAAY;gBAAEA;YAAU,IAAI,CAAC,KAEnC8D,YAAYG,OAAO;QAErBV,QAAQ;QACR,IAAIa,KAAKE,OAAOrF,MAAM,GAAG;QACzB,IAAI,CAACqF,OAAOC,EAAE,IAAI,GAACD,gBAAAA,OAAOE,KAAK,qBAAZF,cAAcrB,IAAI,GAAE;gBAG3BqB;YAFV,sDAAsD;YACtDR,YAAYG,OAAO,GAAG;YACtBR,WAAUa,gBAAAA,OAAO8B,KAAK,YAAZ9B,gBAAgB;YAC1B;QACF;QACApB,QAAQoB,OAAOE,KAAK,CAACvB,IAAI;QACzBD,YAAY;QACZP,SAAS;YAAEC,MAAM;QAAS;IAC5B,GAAG;QAACX;QAAOuB;QAAMX;QAAOyB;KAAK;IAE7B,MAAMiC,aAAavJ,YAAY;QAC7B,MAAMoI,OAAOlB,QAAQC,OAAO;QAC5B,IAAIlC,SAASmD,QAAQA,KAAKjG,MAAM,KAAK,QAAQ,KAAKZ,SAAS8G,OAAO,CAACpD,OAAOmD,KAAKE,OAAO;QACtFlC,QAAQ;QACRY,YAAYG,OAAO,GAAG;QACtBR,UAAU;QACVhB,SAAS;YAAEC,MAAM;QAAO;IAC1B,GAAG;QAACX;KAAM;IAEV,MAAMuE,gBAAgBxJ,YAAY;YAObwH;QANnB,MAAMY,OAAOlB,QAAQC,OAAO;QAC5B,IAAI,CAAClC,SAAS,CAACmD,MAAM;QACrB3B,QAAQ;QACR,MAAMe,SAAS,MAAMjG,SAASkI,OAAO,CAACxE,OAAOmD,KAAKE,OAAO;QACzD7B,QAAQ;QACR,IAAIa,KAAKE,OAAOrF,MAAM,GAAG;QACzB,IAAI,CAACqF,OAAOC,EAAE,IAAI,GAACD,gBAAAA,OAAOE,KAAK,qBAAZF,cAAcrB,IAAI,GAAE;gBAC3BqB;YAAVb,WAAUa,gBAAAA,OAAO8B,KAAK,YAAZ9B,gBAAgB;YAC1B;QACF;QACApB,QAAQoB,OAAOE,KAAK,CAACvB,IAAI;QACzBL,SAAS,EAAE;QACXH,SAAS;YAAEC,MAAM;QAAO;IAC1B,GAAG;QAACX;QAAOqC;KAAK;IAEhB,MAAMoC,eAAe1J,YACnB,OAAO2J,QAA0BC;;QAC/B,MAAMxB,OAAOlB,QAAQC,OAAO;QAC5B,IAAI,CAAClC,SAAS,CAACmD,MAAM;QACrB,IAAI,CAACnB,OAAOE,OAAO,EAAEF,OAAOE,OAAO,GAAG7G;QACtCmG,QAAQ;QACRE,UAAU;QACV,MAAMa,SAAS,MAAMjG,SAASsI,GAAG,CAAC5E,OAAO;YAAEqD,SAASF,KAAKE,OAAO;YAAEqB;WAAWC,SAAU3C,OAAOE,OAAO;QACrG,IAAIG,KAAKE,OAAOrF,MAAM,GAAG,OAAOsE,QAAQ;QACxC,IAAI,CAACe,OAAOC,EAAE,IAAI,CAACD,OAAOE,KAAK,EAAE;gBAGrBF;YAFVf,QAAQ;YACRQ,OAAOE,OAAO,GAAG;YACjBR,WAAUa,gBAAAA,OAAO8B,KAAK,YAAZ9B,gBAAgB;YAC1B7B,SAAS;gBAAEC,MAAM;YAAS;YAC1B;QACF;QACA,MAAM,EAAEO,MAAM2D,IAAI,EAAEC,SAAS,EAAEC,YAAY,EAAEC,eAAe,EAAE,GAAGzC,OAAOE,KAAK;QAC7EtB,QAAQ0D;QACR,MAAMI,WAAW7J,cAAc8J,gBAAgB,CAACP,OAAOrD,SAAS,EAAE;YAChE6D,WAAWhC,KAAKiC,QAAQ;YACxBC,SAAS;YACTC,WAAW,UAAExF,2BAAAA,QAASyF,OAAO,CAACD,WAAW,mBAAI,EAAE;YAC/CE,SAASb,OAAOc,UAAU;YAC1BxC,OAAO0B,OAAOM,QAAQ;QACxB;QACA,MAAMS,cAAcvC,KAAKiC,QAAQ,IAAIH,mBAAAA,WAAY;QACjDvE,SAAS;YAAEC,MAAM;YAAU+D;YAAQI,SAAS,EAAEA,oBAAAA,YAAa;YAAMY;YAAaC,SAAS;QAAK;QAC5FnE,QAAQ;QACR,IAAIkD,WAAW,OAAO;YACpB,MAAMkB,SAAStK;YACf,IAAI,CAACsK,UAAU,CAACb,gBAAgB,CAACC,iBAAiB;gBAChDtE,SAAS;oBAAEC,MAAM;oBAAU+D;oBAAQI,SAAS,EAAEA,oBAAAA,YAAa;oBAAMY;oBAAaC,SAAS;gBAA8C;gBACrI;YACF;YACA,MAAME,YAAY,MAAMD,OACrBE,kBAAkB,CAAC;gBAAEd;gBAAiBD;gBAAcgB,aAAaL;YAAY,GAC7EM,KAAK,CAAC,IAAO,CAAA;oBAAE9I,QAAQ;oBAAmB+I,SAASjH;gBAAU,CAAA;YAChE,IAAI6G,UAAU3I,MAAM,KAAK,aAAa;oBAMwC2I;gBAL5EnF,SAAS;oBACPC,MAAM;oBACN+D;oBACAI,SAAS,EAAEA,oBAAAA,YAAa;oBACxBY;oBACAC,SAASE,UAAU3I,MAAM,KAAK,aAAa,+BAA+B2I,qBAAAA,UAAUI,OAAO,YAAjBJ,qBAAqB;gBACjG;YACF;QACF;IACF,GACA;QAAC7F;QAAOqC;QAAMvC;KAAQ;IAGxB,gEAAgE;IAChE,MAAMgF,YAAYrE,MAAME,IAAI,KAAK,WAAWF,MAAMqE,SAAS,GAAG;IAC9D,MAAMoB,gBAAgBzF,MAAME,IAAI,KAAK,WAAWnC,QAAQiC,MAAMkF,OAAO,IAAI;IACzE3K,UAAU;QACR,IAAI,CAACgF,SAAS,CAAC8E,aAAaoB,eAAe,OAAOlH;QAClD,MAAMmE,OAAOlB,QAAQC,OAAO;QAC5B,IAAI,CAACiB,MAAM,OAAOnE;QAClB,IAAI6D,SAAS;QACb,MAAMH,QAAQC,YAAY;gBAIXJ,eAUEsC;YAbf,MAAMtC,SAAS,MAAMjG,SAAS6J,aAAa,CAACnG,OAAOmD,KAAKE,OAAO,EAAEyB;YACjE,IAAI,CAACjC,QAAQ;YACb,IAAIR,KAAKE,OAAOrF,MAAM,GAAG;YACzB,MAAM2H,QAAOtC,gBAAAA,OAAOE,KAAK,qBAAZF,cAAcrB,IAAI;YAC/B,IAAI,CAAC2D,MAAM;YACX1D,QAAQ0D;YACR,IAAIA,KAAK3H,MAAM,KAAK,QAAQ;gBAC1B0F,cAAcF;gBACd7B,SAAS,EAAE;gBACXmB,OAAOE,OAAO,GAAG;gBACjBxB,SAAS;oBAAEC,MAAM;gBAAU;gBAC3B;YACF;YACA,MAAMzD,SAAS2H,EAAAA,gBAAAA,KAAKuB,OAAO,qBAAZvB,cAAc/H,EAAE,MAAKgI,YAAYD,KAAKuB,OAAO,CAAClJ,MAAM,GAAG;YACtE,IAAIA,WAAW,YAAYA,WAAW,YAAY;gBAChD0F,cAAcF;gBACdV,OAAOE,OAAO,GAAG;gBACjBxB,SAAS,CAACwB;;wBAEmB2C;2BAD3B3C,QAAQvB,IAAI,KAAK,WACb,aAAKuB;wBAASyD,OAAO,WAAEd,gBAAAA,KAAKuB,OAAO,qBAAZvB,cAAcwB,cAAc,mBAAI;yBACvDnE;;YAER;QACF,GAAGxF;QACH,OAAO;YACLmG,SAAS;YACTD,cAAcF;QAChB;IACF,GAAG;QAAC1C;QAAO8E;QAAWoB;QAAe7D;KAAK;IAE1C,MAAMiE,gBAAgBvL,YAAY;YAQ5BwL,cACAA;QARJ,MAAMpD,OAAOlB,QAAQC,OAAO;QAC5B,IAAI,CAAClC,SAAS,CAACmD,QAAQ1C,MAAME,IAAI,KAAK,UAAU;QAChDa,QAAQ;QACR,IAAIf,MAAMqE,SAAS,IAAI,CAACrE,MAAMkF,OAAO,EAAE,MAAMrJ,SAASgK,aAAa,CAACtG,OAAOmD,KAAKE,OAAO,EAAE5C,MAAMqE,SAAS;QACxG,MAAMyB,QAAQ,MAAMjK,SAAS4E,IAAI,CAAClB,OAAOmD,KAAKE,OAAO;QACrD7B,QAAQ;QACRQ,OAAOE,OAAO,GAAG;QACjB,KAAIqE,eAAAA,MAAM9D,KAAK,qBAAX8D,aAAarF,IAAI,EAAEC,QAAQoF,MAAM9D,KAAK,CAACvB,IAAI;QAC/C,IAAIqF,EAAAA,gBAAAA,MAAM9D,KAAK,qBAAX8D,cAAarF,IAAI,CAAChE,MAAM,MAAK,QAAQ;YACvCwD,SAAS;gBAAEC,MAAM;YAAU;YAC3B;QACF;QACAD,SAAS;YAAEC,MAAM;QAAS;IAC5B,GAAG;QAACX;QAAOS;KAAM;IAEjB,MAAM+F,gBAAgBzL,YACpB,OAAO4J;QACL,MAAM8B,OAAOxE,QAAQC,OAAO;QAC5B,IAAI,CAAClC,SAAS,CAACyG,QAAQ,CAAC9B,OAAO+B,cAAc,EAAE;QAC/ClF,QAAQ;QACR,MAAMe,SAAS,MAAMjG,SAASqK,OAAO,CAAC3G,OAAO;YAC3CqD,SAASoD,KAAKpD,OAAO;YACrBuD,SAASjC,OAAO+B,cAAc;WAC1B/B,OAAOkC,KAAK,GAAG;YAAEC,IAAInC,OAAOkC,KAAK;QAAC,IAAI,CAAC,GACvClC,OAAOoC,KAAK,GAAG;YAAED,IAAInC,OAAOoC,KAAK;QAAC,IAAI,CAAC,GACvCpC,OAAOqC,cAAc,GAAG;YAAEA,gBAAgB;QAAK,IAAI,CAAC;QAE1DxF,QAAQ;QACR,IAAIa,KAAKE,OAAOrF,MAAM,GAAG;QACzB,IAAI,CAACqF,OAAOC,EAAE,EAAE;gBACJD;YAAVb,WAAUa,gBAAAA,OAAO8B,KAAK,YAAZ9B,gBAAgB;QAC5B;QACA7B,SAAS;YAAEC,MAAM;QAAO;IAC1B,GACA;QAACX;QAAOqC;KAAK;IAGf,MAAMuC,MAAuB3J,QAC3B,IAAO,CAAA;YACLgM,QAAQzI,QAAQsB,CAAAA,2BAAAA,QAASoH,QAAQ,CAACC,WAAW,KAAIrH,QAAQoH,QAAQ,CAACD,MAAM;YACxEG,KAAK5I,QAAQsB,CAAAA,2BAAAA,QAASoH,QAAQ,CAACC,WAAW,KAAI7L;YAC9CkJ,SAAShG,QAAQsB,2BAAAA,QAASoH,QAAQ,CAACG,YAAY;QACjD,CAAA,GACA;QAACvH;KAAQ;IAGX,MAAMwH,YAAYvM,YAChB,CAAC2J;QACC,IAAI5E,2BAAAA,QAASyF,OAAO,CAACF,OAAO,EAAE;YAC5B3E,SAAS;gBAAEC,MAAM;gBAAO+D;YAAO;YAC/B;QACF;QACArD,OAAO;YAAEC,WAAW;QAAO;QAC3B,KAAKmD,aAAaC,QAAQ;YAAEpD,WAAW;QAAO;IAChD,GACA;QAACxB;QAAS2E;KAAa;IAGzB,IAAIzE,UAAUhB,WAAW;QACvB,qBACE,KAAC3E;YAAIkN,IAAI;gBAAEC,WAAW;gBAAUC,SAAS;gBAAQC,YAAY;YAAS;sBACpE,cAAA,KAACnN;gBAAiBoN,cAAW;;;IAGnC;IAEA,IAAI,CAAC3H,OAAO;QACV,qBACE,KAACrE;YACCiM,MAAK;YACLC,UAAU,CAAChD;gBACTrI,gBAAgBqI;gBAChB5E,SAAS4E;YACX;;IAGN;IAEA,MAAMiD,oBAAWhI,2BAAAA,QAASgI,QAAQ,oBAAI;IACtC,IAAIC;IACJ,IAAItH,MAAME,IAAI,KAAK,SAAS;QAC1BoH,uBACE,KAACrM;YAAsBoM,UAAUA;YAAU7B,SAAS6B,CAAAA,4BAAAA,SAAU7B,OAAO,KAAI;sBACvE,cAAA,KAAC3L;gBACCiD,SAAQ;gBACRyK,MAAK;gBACLC,SAAS,IAAMvH,SAAS;wBAAEC,MAAM;oBAAO;gBACvC4G,IAAI,CAACW,QAAW,aAAKnM,kBAAkBmM;wBAAQC,IAAI;;0BAElD;;;IAIT,OAAO,IAAI1H,MAAME,IAAI,KAAK,QAAQ;QAChCoH,uBACE;;gBACGtG,uBACC,KAACrH;oBAAMgO,UAAS;oBAAUC,SAAS,IAAM3G,UAAU;oBAAO6F,IAAI;wBAAEe,GAAG;wBAAGC,IAAI;oBAAE;8BACzE9G;qBAED;8BACJ,KAACtF;oBACCgE,SAASA;oBACTqI,SAASnI,kBAAkB,CAACF;oBAC5BI,YAAYA;oBACZkI,YAAYjI;oBACZkI,WAAWxE;oBACXtD,OAAOA;oBACPmC,UAAUA;oBACV4F,UAAU,IAAM,KAAKvE;oBACrBwE,YAAY,CAAC3J,KAAKI;wBAChB0C,YAAYG,OAAO,GAAG;wBACtBrB,SAAS,CAACqB,UACR7C,YAAY,IACR6C,QAAQ3D,MAAM,CAAC,CAACwF,OAASA,KAAK9E,GAAG,KAAKA,OACtCiD,QAAQ5E,GAAG,CAAC,CAACyG,OAAUA,KAAK9E,GAAG,KAAKA,MAAM,aAAK8E;oCAAM1E;qCAAa0E;oBAE1E;oBACA/C,UAAUA;oBACV6H,YAAY5H;oBACZM,MAAMA;;;;IAId,OAAO,IAAId,MAAME,IAAI,KAAK,YAAYO,MAAM;QAC1C6G,uBACE,KAAC7L;YACCgF,MAAMA;YACN6B,UAAUA;YACV6B,KAAKA;YACLrD,MAAMA;YACNE,QAAQA;YACRqH,OAAOxB;YACPyB,WAAW,IAAM,KAAKxE;YACtByE,QAAQ1E;;IAGd,OAAO,IAAI7D,MAAME,IAAI,KAAK,SAASO,QAAQpB,SAAS;QAClDiI,uBACE,KAACvN;YAAUyO,UAAS;YAAK1B,IAAI;gBAAE2B,IAAI;YAAE;sBACnC,cAAA,MAACpO;gBAAMqO,SAAS;gBAAG5B,IAAI;oBAAE6B,YAAY;gBAAS;;kCAC5C,KAAC3N;wBAAoBqM,UAAUA;;kCAC/B,KAAChM;wBACCsF,KAAK;4BAAE+D,WAAWjE,KAAKkE,QAAQ;4BAAEE,aAAaxF,QAAQyF,OAAO,CAACD,WAAW;4BAAE+D,aAAa;wBAAK;wBAC7FC,UAAU,CAAC,MAAM,EAAEpI,KAAKmC,OAAO,EAAE;wBACjC9B,MAAMA;wBACNwB,UAAUA;wBACVwG,UAAU,CAAC5E;gCAEIA,mBAEqCA;4BAHlD,MAAME,OAAkB;gCACtBvD,SAAS,GAAEqD,oBAAAA,OAAOrD,SAAS,YAAhBqD,oBAAoB;+BAC3BA,OAAOc,UAAU,GAAG;gCAAEA,YAAYd,OAAOc,UAAU;4BAAC,IAAI,CAAC,GACzDd,OAAOrD,SAAS,KAAK,WAAW;gCAAE2D,QAAQ,GAAEN,mBAAAA,OAAOM,QAAQ,YAAfN,mBAAmB;4BAAE,IAAI,CAAC;4BAE5EtD,OAAOwD;4BACP,KAAKJ,aAAahE,MAAMiE,MAAM,EAAEG;wBAClC;;kCAEF,KAACvK;wBAAO2N,SAAS,IAAMvH,SAAS;gCAAEC,MAAM;4BAAS;wBAAI6I,UAAUjI;kCAC5D;;;;;IAKX,OAAO,IAAId,MAAME,IAAI,KAAK,YAAYO,MAAM;QAC1C6G,uBACE,KAAC9L;YACCyJ,aAAajF,MAAMiF,WAAW;YAC9B3C,UAAUA;YACV2B,QAAQjE,MAAMiE,MAAM;YACpBiB,SAASlF,MAAMkF,OAAO;YACtB8D,UAAUjL,QAAQsB,CAAAA,2BAAAA,QAAS2J,QAAQ,KAAIhJ,MAAMiE,MAAM,KAAK;YACxDnD,MAAMA;YACNmI,UAAU,IAAM,KAAKpD;YACrBqD,SAAS,IAAM,KAAKlF,aAAahE,MAAMiE,MAAM,EAAEtD;YAC/C2H,WAAWnE,IAAIJ,OAAO,GAAG,IAAM,KAAKD,kBAAkB;YACtDqF,YACEnJ,MAAMqE,SAAS,GACX,IAAM,KAAKxI,SAASuN,QAAQ,CAAC7J,OAAOkB,KAAKmC,OAAO,EAAE5C,MAAMqE,SAAS,IACjE;;IAIZ,OAAO,IAAIrE,MAAME,IAAI,KAAK,aAAaO,QAAQpB,SAAS;QACtDiI,uBACE,KAACvN;YAAUyO,UAAS;YAAK1B,IAAI;gBAAE2B,IAAI;YAAE;sBACnC,cAAA,MAACpO;gBAAMqO,SAAS;gBAAG5B,IAAI;oBAAE6B,YAAY;gBAAS;;kCAC5C,KAAC3N;wBAAoBqM,UAAUA;;kCAC/B,KAACjM;wBACC8K,SAAS;4BAAEmD,UAAUhK,QAAQiK,QAAQ;4BAAEC,gBAAgBlK,QAAQkK,cAAc;wBAAC;wBAC9EV,UAAU,CAAC,MAAM,EAAEpI,KAAKmC,OAAO,EAAE;wBACjC9B,MAAMA;wBACNgI,UAAU,CAAC5E,SAAW,KAAK6B,cAAc7B;;;;;IAKnD,OAAO,IAAIlE,MAAME,IAAI,KAAK,UAAUO,MAAM;QACxC6G,uBAAS,KAAC/L;YAAUkF,MAAMA;YAAM6B,UAAUA;YAAUkH,QAAQ/G;;IAC9D,OAAO;QACL6E,uBAAS,KAACrM;YAAsBoM,UAAUA;YAAUvG,IAAI;;IAC1D;IAEA,qBACE,MAAClH;QAAekN,IAAI;YAAE2C,UAAU;YAAY1C,WAAW;QAAS;;YAC7D7F,wBACC,KAACvH;gBAAMgO,UAAS;gBAAUb,IAAI;oBAAE2C,UAAU;oBAASC,KAAK;oBAAGC,MAAM;oBAAGC,OAAO;oBAAGC,QAAQ,CAACpC,QAAUA,MAAMoC,MAAM,CAACC,KAAK,GAAG;gBAAE;0BACrH;iBAED;YACHxC;0BACD,KAACxM;gBACCqB,SAASkE,cAAcnE,iBAAiBmE,eAAe;gBACvDuH,SAAS,IAAMtH,eAAe;gBAC9ByJ,WAAW,CAAC3M;oBACV,MAAMjB,UAAUkE;oBAChBC,eAAe;oBACf,IAAInE,SAASkH,UAAUlH,SAASiB;gBAClC;gBACA4M,aAAazH;gBACb0H,YAAY;gBACZC,aAAavP,cAAcoE,sBAAsB;;0BAEnD,MAAC/E;gBAAO0I,MAAMpD,KAAK6K,OAAO,KAAK;gBAAMvC,SAAStI,KAAK8K,SAAS;gBAAE5B,UAAS;gBAAK6B,SAAS;;kCACnF,KAACjQ;kCAAa;;kCACd,KAACF;kCACC,cAAA,KAACC;sCACE,CAAC,8BAA8B,GAAEmF,gBAAAA,KAAK6K,OAAO,YAAZ7K,gBAAgB,EAAE,SAAS,CAAC;;;kCAGlE,MAACrF;;0CACC,KAACJ;gCAAO2N,SAAS/E;0CAAQ;;0CACzB,KAAC5I;gCAAOiD,SAAQ;gCAAY0K,SAASlI,KAAK8K,SAAS;0CAChD;;;;;;YAINpK,MAAME,IAAI,KAAK,WAAWF,MAAME,IAAI,KAAK,uBACxC,KAACvE;gBAAkB4D,OAAOA;gBAAO+K,QAAQ3I;gBAAU4I,gBAAgB5I;iBACjE;;OAnCIP;AAsCd;AAEAjC,aAAaqL,WAAW,GAAG"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-kiosk-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 type { ConsolePublicPageProps } from '@aglyn/aglyn'\nimport Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport CircularProgress from '@mui/material/CircularProgress'\nimport Container from '@mui/material/Container'\nimport Dialog from '@mui/material/Dialog'\nimport DialogActions from '@mui/material/DialogActions'\nimport DialogContent from '@mui/material/DialogContent'\nimport DialogContentText from '@mui/material/DialogContentText'\nimport DialogTitle from '@mui/material/DialogTitle'\nimport Stack from '@mui/material/Stack'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport * as CommerceModel from '../../model'\nimport { newAttemptKey, posNativeBridge } from './pos/pos-api'\nimport { PosItemDialog, posItemNeedsChoice, type PosItemChoice } from './pos/pos-item-dialog.component'\nimport { PosDisplayBrandMark, PosDisplayBrandScreen } from './pos-display/brand-screen'\nimport { PosDisplayPairingScreen } from './pos-display/pairing-screen'\nimport { displayMoney, type PosDisplayAnswer } from './pos-display/pos-display-api'\nimport { PosDisplayReceiptScreen } from './pos-display/receipt-screen'\nimport { PosDisplayTipScreen, posDisplayTouchSx } from './pos-display/tip-screen'\nimport { KioskDone, KioskPaying, KioskReview, type KioskPayOptions } from './pos-kiosk/kiosk-checkout'\nimport { KioskMenu, type KioskCartLine } from './pos-kiosk/kiosk-menu'\nimport { KioskStaffControl } from './pos-kiosk/kiosk-staff'\nimport {\n clearKioskCustomerStorage,\n kioskApi,\n readKioskToken,\n storeKioskToken,\n} from './pos-kiosk/pos-kiosk-api'\nimport { useKioskIdle } from './pos-kiosk/use-kiosk-idle'\n\n/** How often the kiosk asks after a card payment in flight. */\nexport const POS_KIOSK_PAYMENT_POLL_MS = 1_500\n\ntype Phase =\n | { kind: 'start' }\n | { kind: 'menu' }\n | { kind: 'review' }\n | { kind: 'tip'; method: 'reader' | 'tap' }\n | { kind: 'paying'; method: 'reader' | 'tap'; paymentId: string | null; chargeCents: number; failure: string | null }\n | { kind: 'receipt' }\n | { kind: 'done' }\n\ntype TipAnswer = { tipChoice: 'percent' | 'custom' | 'none'; tipPercent?: number; tipCents?: number }\n\n/** A product as the register's item sheet takes it, from the kiosk's catalog. */\nexport function kioskItemProduct(product: CommerceModel.PosKioskProduct) {\n return {\n $id: product.id,\n name: product.name,\n slug: product.id,\n type: 'physical',\n status: 'active',\n options: product.options,\n modifierGroups: product.modifierGroups,\n variants: product.variants.map((variant) => ({\n id: variant.id,\n options: variant.options,\n priceUsd: variant.priceCents / 100,\n // A sold-out variant reads as zero on hand; anything else as untracked,\n // so the kiosk never learns or shows a stock count.\n inventory: variant.soldOut ? 0 : null,\n })),\n } as unknown as CommerceModel.HostProduct & { $id: string }\n}\n\n/** The cart line a choice makes: same item and choices merge. */\nexport function kioskCartLine(\n product: CommerceModel.PosKioskProduct,\n choice: PosItemChoice,\n): KioskCartLine {\n const variant = product.variants.find((candidate) => candidate.id === choice.variant.id) ?? product.variants[0]!\n const picked = choice.modifiers\n .map((pick) => {\n const group = product.modifierGroups.find((candidate) => candidate.id === pick.groupId)\n return group?.options.find((option) => option.id === pick.optionId)\n })\n .filter((option): option is CommerceModel.ProductModifierOption => Boolean(option))\n const label = CommerceModel.lineLabelWithModifiers(\n Object.keys(variant.options).length ? Object.values(variant.options).join(' / ') : undefined,\n picked,\n )\n return {\n key: `${product.id}:${variant.id}:${CommerceModel.modifierSelectionKey(choice.modifiers)}`,\n productId: product.id,\n ...(variant.id !== 'default' || product.variants.length > 1 ? { variantId: variant.id } : {}),\n quantity: Math.min(CommerceModel.POS_KIOSK_MAX_QUANTITY, choice.quantity),\n ...(choice.modifiers.length ? { modifiers: choice.modifiers } : {}),\n name: product.name,\n ...(label ? { label } : {}),\n // A choice priced by variant adds its price on this one (AGL-4100).\n unitCents:\n variant.priceCents +\n picked.reduce((sum, option) => sum + CommerceModel.modifierOptionPriceCents(option, variant.id), 0),\n }\n}\n\n/**\n * The self-service kiosk (AGL-3623), served at `/kiosk/commerce/pos-kiosk`\n * with no staff session: a customer builds their own order and pays on the\n * register's card reader or Tap to Pay, or sends it to the counter.\n *\n * It holds one secret — the kiosk token from pairing — and everything the\n * customer chooses or types lives in this component's memory only. The idle\n * reset (and \"Done\", and \"Start over\") voids an unpaid order, drops the\n * cart, the tip and any email or phone, sweeps the kiosk's storage keys, and\n * remounts every screen, so the next customer finds nothing of the last.\n */\nexport default function PosKioskPage(_props: ConsolePublicPageProps) {\n const [token, setToken] = useState<string | null | undefined>(undefined)\n const [context, setContext] = useState<CommerceModel.PosKioskContext | null>(null)\n const [catalog, setCatalog] = useState<CommerceModel.PosKioskCatalog | null>(null)\n const [catalogLoading, setCatalogLoading] = useState(false)\n const [categoryId, setCategoryId] = useState<string | null>(null)\n const [phase, setPhase] = useState<Phase>({ kind: 'start' })\n const [lines, setLines] = useState<KioskCartLine[]>([])\n const [itemProduct, setItemProduct] = useState<CommerceModel.PosKioskProduct | null>(null)\n const [cartOpen, setCartOpen] = useState(false)\n const [sale, setSale] = useState<CommerceModel.PosKioskSale | null>(null)\n const [tip, setTip] = useState<TipAnswer>({ tipChoice: 'none' })\n const [busy, setBusy] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n const [offline, setOffline] = useState(false)\n // Bumped by every reset: keys every screen, so inputs never carry over.\n const [turn, setTurn] = useState(0)\n // One attempt per cart, and one per press of a payment button.\n const checkoutKey = useRef<string | null>(null)\n const payKey = useRef<string | null>(null)\n const saleRef = useRef(sale)\n saleRef.current = sale\n const phaseRef = useRef(phase)\n phaseRef.current = phase\n\n useEffect(() => {\n setToken(readKioskToken())\n }, [])\n\n const unpaired = useCallback(() => {\n storeKioskToken(null)\n clearKioskCustomerStorage()\n setToken(null)\n setContext(null)\n setCatalog(null)\n setSale(null)\n setLines([])\n setPhase({ kind: 'start' })\n }, [])\n\n /** A response that says the kiosk is no longer paired ends the session. */\n const lost = useCallback(\n (status: number) => {\n if (status === 401) {\n unpaired()\n return true\n }\n return false\n },\n [unpaired],\n )\n\n // The kiosk's settings and the menu: read when paired, and again every\n // ten minutes while idle on the start screen, so an edit reaches it.\n const refresh = useCallback(async () => {\n if (!token) return\n const result = await kioskApi.context(token)\n if (lost(result.status)) return\n setOffline(!result.ok && result.status === 0)\n if (result.ok && result.value) setContext(result.value)\n }, [token, lost])\n\n useEffect(() => {\n void refresh()\n const timer = setInterval(() => {\n if (phaseRef.current.kind === 'start') void refresh()\n }, 10 * 60 * 1000)\n return () => clearInterval(timer)\n }, [refresh])\n\n useEffect(() => {\n if (!token) return undefined\n let active = true\n setCatalogLoading(true)\n void kioskApi.catalog(token, categoryId).then((result) => {\n if (!active) return\n setCatalogLoading(false)\n if (lost(result.status)) return\n if (result.ok && result.value) setCatalog(result.value)\n else setOffline(result.status === 0)\n })\n return () => {\n active = false\n }\n }, [token, categoryId, turn, lost])\n\n const currency = context?.currency ?? catalog?.currency ?? 'usd'\n const money = useCallback((cents: number) => displayMoney(cents, currency), [currency])\n\n /**\n * THE RESET: the unpaid order voided, every customer detail dropped from\n * memory and storage, and the screens remounted on the start screen.\n */\n const reset = useCallback(() => {\n const open = saleRef.current\n if (token && open && open.status === 'open') void kioskApi.abandon(token, open.orderId)\n setSale(null)\n setLines([])\n setTip({ tipChoice: 'none' })\n setItemProduct(null)\n setCartOpen(false)\n setNotice(null)\n setCategoryId(null)\n checkoutKey.current = null\n payKey.current = null\n clearKioskCustomerStorage()\n setPhase({ kind: 'start' })\n setTurn((value) => value + 1)\n }, [token])\n\n const idle = useKioskIdle({\n // Never while a card is being collected: the customer is at the reader.\n active: Boolean(token) && phase.kind !== 'start' && phase.kind !== 'paying',\n idleSeconds: context?.idleSeconds ?? CommerceModel.POS_KIOSK_IDLE_SECONDS_DEFAULT,\n warningSeconds: CommerceModel.POS_KIOSK_IDLE_WARNING_SECONDS,\n onExpire: reset,\n })\n\n // The order-number screen returns to the start on its own.\n useEffect(() => {\n if (phase.kind !== 'done') return undefined\n const timer = setTimeout(reset, CommerceModel.POS_KIOSK_DONE_SECONDS * 1000)\n return () => clearTimeout(timer)\n }, [phase.kind, reset])\n\n const addChoice = useCallback((product: CommerceModel.PosKioskProduct, choice: PosItemChoice) => {\n const line = kioskCartLine(product, choice)\n checkoutKey.current = null\n setLines((current) => {\n const existing = current.find((candidate) => candidate.key === line.key)\n if (existing) {\n return current.map((candidate) =>\n candidate.key === line.key\n ? { ...candidate, quantity: Math.min(CommerceModel.POS_KIOSK_MAX_QUANTITY, candidate.quantity + line.quantity) }\n : candidate,\n )\n }\n if (current.length >= CommerceModel.POS_KIOSK_MAX_LINES) return current\n return [...current, line]\n })\n }, [])\n\n const tapProduct = useCallback(\n (product: CommerceModel.PosKioskProduct) => {\n const asItem = kioskItemProduct(product)\n if (posItemNeedsChoice(asItem)) {\n setItemProduct(product)\n return\n }\n const variant = asItem.variants[0]\n if (!variant || product.variants[0]?.soldOut) return\n addChoice(product, { variant, modifiers: [], quantity: 1 })\n },\n [addChoice],\n )\n\n const checkout = useCallback(async () => {\n if (!token || busy || lines.length === 0) return\n if (!checkoutKey.current) checkoutKey.current = newAttemptKey()\n setBusy(true)\n setNotice(null)\n const result = await kioskApi.checkout(\n token,\n lines.map(({ productId, variantId, quantity, modifiers }) => ({\n productId,\n ...(variantId ? { variantId } : {}),\n quantity,\n ...(modifiers ? { modifiers } : {}),\n })),\n checkoutKey.current,\n )\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok || !result.value?.sale) {\n // A refused cart is changed before it is tried again.\n checkoutKey.current = null\n setNotice(result.error ?? 'Your order could not be priced. Try again.')\n return\n }\n setSale(result.value.sale)\n setCartOpen(false)\n setPhase({ kind: 'review' })\n }, [token, busy, lines, lost])\n\n const backToMenu = useCallback(() => {\n const open = saleRef.current\n if (token && open && open.status === 'open') void kioskApi.abandon(token, open.orderId)\n setSale(null)\n checkoutKey.current = null\n setNotice(null)\n setPhase({ kind: 'menu' })\n }, [token])\n\n const sendToCounter = useCallback(async () => {\n const open = saleRef.current\n if (!token || !open) return\n setBusy(true)\n const result = await kioskApi.counter(token, open.orderId)\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok || !result.value?.sale) {\n setNotice(result.error ?? 'Your order could not be sent to the counter.')\n return\n }\n setSale(result.value.sale)\n setLines([])\n setPhase({ kind: 'done' })\n }, [token, lost])\n\n const startPayment = useCallback(\n async (method: 'reader' | 'tap', answer: TipAnswer) => {\n const open = saleRef.current\n if (!token || !open) return\n if (!payKey.current) payKey.current = newAttemptKey()\n setBusy(true)\n setNotice(null)\n const result = await kioskApi.pay(token, { orderId: open.orderId, method, ...answer }, payKey.current)\n if (lost(result.status)) return setBusy(false)\n if (!result.ok || !result.value) {\n setBusy(false)\n payKey.current = null\n setNotice(result.error ?? 'The card payment could not be started.')\n setPhase({ kind: 'review' })\n return\n }\n const { sale: next, paymentId, clientSecret, paymentIntentId } = result.value\n setSale(next)\n const tipCents = CommerceModel.posKioskTipCents(answer.tipChoice, {\n baseCents: open.dueCents,\n enabled: true,\n percentages: context?.tipping.percentages ?? [],\n percent: answer.tipPercent,\n cents: answer.tipCents,\n })\n const chargeCents = open.dueCents + (tipCents ?? 0)\n setPhase({ kind: 'paying', method, paymentId: paymentId ?? null, chargeCents, failure: null })\n setBusy(false)\n if (method === 'tap') {\n const bridge = posNativeBridge()\n if (!bridge || !clientSecret || !paymentIntentId) {\n setPhase({ kind: 'paying', method, paymentId: paymentId ?? null, chargeCents, failure: 'Tap to Pay is not available on this device.' })\n return\n }\n const collected = await bridge\n .collectCardPayment({ paymentIntentId, clientSecret, amountCents: chargeCents })\n .catch(() => ({ status: 'failed' as const, message: undefined }))\n if (collected.status !== 'collected') {\n setPhase({\n kind: 'paying',\n method,\n paymentId: paymentId ?? null,\n chargeCents,\n failure: collected.status === 'canceled' ? 'The payment was canceled.' : (collected.message ?? 'The card was not read.'),\n })\n }\n }\n },\n [token, lost, context],\n )\n\n // The card in flight, asked after until it is paid or it fails.\n const paymentId = phase.kind === 'paying' ? phase.paymentId : null\n const paymentFailed = phase.kind === 'paying' ? Boolean(phase.failure) : false\n useEffect(() => {\n if (!token || !paymentId || paymentFailed) return undefined\n const open = saleRef.current\n if (!open) return undefined\n let active = true\n const timer = setInterval(async () => {\n const result = await kioskApi.paymentStatus(token, open.orderId, paymentId)\n if (!active) return\n if (lost(result.status)) return\n const next = result.value?.sale\n if (!next) return\n setSale(next)\n if (next.status === 'paid') {\n clearInterval(timer)\n setLines([])\n payKey.current = null\n setPhase({ kind: 'receipt' })\n return\n }\n const status = next.payment?.id === paymentId ? next.payment.status : ''\n if (status === 'failed' || status === 'canceled') {\n clearInterval(timer)\n payKey.current = null\n setPhase((current) =>\n current.kind === 'paying'\n ? { ...current, failure: next.payment?.failureMessage ?? 'The card was declined.' }\n : current,\n )\n }\n }, POS_KIOSK_PAYMENT_POLL_MS)\n return () => {\n active = false\n clearInterval(timer)\n }\n }, [token, paymentId, paymentFailed, lost])\n\n const cancelPayment = useCallback(async () => {\n const open = saleRef.current\n if (!token || !open || phase.kind !== 'paying') return\n setBusy(true)\n if (phase.paymentId && !phase.failure) await kioskApi.cancelPayment(token, open.orderId, phase.paymentId)\n const fresh = await kioskApi.sale(token, open.orderId)\n setBusy(false)\n payKey.current = null\n if (fresh.value?.sale) setSale(fresh.value.sale)\n if (fresh.value?.sale.status === 'paid') {\n setPhase({ kind: 'receipt' })\n return\n }\n setPhase({ kind: 'review' })\n }, [token, phase])\n\n const answerReceipt = useCallback(\n async (answer: PosDisplayAnswer) => {\n const paid = saleRef.current\n if (!token || !paid || !answer.receiptChannel) return\n setBusy(true)\n const result = await kioskApi.receipt(token, {\n orderId: paid.orderId,\n channel: answer.receiptChannel,\n ...(answer.email ? { to: answer.email } : {}),\n ...(answer.phone ? { to: answer.phone } : {}),\n ...(answer.marketingOptIn ? { marketingOptIn: true } : {}),\n })\n setBusy(false)\n if (lost(result.status)) return\n if (!result.ok) {\n setNotice(result.error ?? 'Your receipt could not be sent. Ask at the counter.')\n }\n setPhase({ kind: 'done' })\n },\n [token, lost],\n )\n\n const pay: KioskPayOptions = useMemo(\n () => ({\n reader: Boolean(context?.payments.cardPresent && context.payments.reader),\n tap: Boolean(context?.payments.cardPresent && posNativeBridge()),\n counter: Boolean(context?.payments.payAtCounter),\n }),\n [context],\n )\n\n const choosePay = useCallback(\n (method: 'reader' | 'tap') => {\n if (context?.tipping.enabled) {\n setPhase({ kind: 'tip', method })\n return\n }\n setTip({ tipChoice: 'none' })\n void startPayment(method, { tipChoice: 'none' })\n },\n [context, startPayment],\n )\n\n if (token === undefined) {\n return (\n <Box sx={{ minHeight: '100dvh', display: 'grid', placeItems: 'center' }}>\n <CircularProgress aria-label=\"Loading\" />\n </Box>\n )\n }\n\n if (!token) {\n return (\n <PosDisplayPairingScreen\n mode=\"kiosk\"\n onPaired={(next) => {\n storeKioskToken(next)\n setToken(next)\n }}\n />\n )\n }\n\n const branding = context?.branding ?? null\n let screen\n if (phase.kind === 'start') {\n screen = (\n <PosDisplayBrandScreen branding={branding} message={branding?.message || 'Order here'}>\n <Button\n variant=\"contained\"\n size=\"large\"\n onClick={() => setPhase({ kind: 'menu' })}\n sx={(theme) => ({ ...posDisplayTouchSx(theme), px: 6 })}\n >\n {'Start order'}\n </Button>\n </PosDisplayBrandScreen>\n )\n } else if (phase.kind === 'menu') {\n screen = (\n <>\n {notice ? (\n <Alert severity=\"warning\" onClose={() => setNotice(null)} sx={{ m: 2, mb: 0 }}>\n {notice}\n </Alert>\n ) : null}\n <KioskMenu\n catalog={catalog}\n loading={catalogLoading && !catalog}\n categoryId={categoryId}\n onCategory={setCategoryId}\n onProduct={tapProduct}\n lines={lines}\n currency={currency}\n onReview={() => void checkout()}\n onQuantity={(key, quantity) => {\n checkoutKey.current = null\n setLines((current) =>\n quantity <= 0\n ? current.filter((line) => line.key !== key)\n : current.map((line) => (line.key === key ? { ...line, quantity } : line)),\n )\n }}\n cartOpen={cartOpen}\n onCartOpen={setCartOpen}\n busy={busy}\n />\n </>\n )\n } else if (phase.kind === 'review' && sale) {\n screen = (\n <KioskReview\n sale={sale}\n currency={currency}\n pay={pay}\n busy={busy}\n notice={notice}\n onPay={choosePay}\n onCounter={() => void sendToCounter()}\n onBack={backToMenu}\n />\n )\n } else if (phase.kind === 'tip' && sale && context) {\n screen = (\n <Container maxWidth=\"md\" sx={{ py: 4 }}>\n <Stack spacing={4} sx={{ alignItems: 'center' }}>\n <PosDisplayBrandMark branding={branding} />\n <PosDisplayTipScreen\n tip={{ baseCents: sale.dueCents, percentages: context.tipping.percentages, allowCustom: true }}\n promptId={`kiosk-${sale.orderId}`}\n busy={busy}\n currency={currency}\n onAnswer={(answer) => {\n const next: TipAnswer = {\n tipChoice: answer.tipChoice ?? 'none',\n ...(answer.tipPercent ? { tipPercent: answer.tipPercent } : {}),\n ...(answer.tipChoice === 'custom' ? { tipCents: answer.tipCents ?? 0 } : {}),\n }\n setTip(next)\n void startPayment(phase.method, next)\n }}\n />\n <Button onClick={() => setPhase({ kind: 'review' })} disabled={busy}>\n {'Back'}\n </Button>\n </Stack>\n </Container>\n )\n } else if (phase.kind === 'paying' && sale) {\n screen = (\n <KioskPaying\n chargeCents={phase.chargeCents}\n currency={currency}\n method={phase.method}\n failure={phase.failure}\n testMode={Boolean(context?.testMode && phase.method === 'reader')}\n busy={busy}\n onCancel={() => void cancelPayment()}\n onRetry={() => void startPayment(phase.method, tip)}\n onCounter={pay.counter ? () => void sendToCounter() : null}\n onSimulate={\n phase.paymentId\n ? () => void kioskApi.simulate(token, sale.orderId, phase.paymentId as string)\n : null\n }\n />\n )\n } else if (phase.kind === 'receipt' && sale && context) {\n screen = (\n <Container maxWidth=\"md\" sx={{ py: 4 }}>\n <Stack spacing={4} sx={{ alignItems: 'center' }}>\n <PosDisplayBrandMark branding={branding} />\n <PosDisplayReceiptScreen\n receipt={{ channels: context.receipts, offerMarketing: context.offerMarketing }}\n promptId={`kiosk-${sale.orderId}`}\n busy={busy}\n onAnswer={(answer) => void answerReceipt(answer)}\n />\n </Stack>\n </Container>\n )\n } else if (phase.kind === 'done' && sale) {\n screen = <KioskDone sale={sale} currency={currency} onDone={reset} />\n } else {\n screen = <PosDisplayBrandScreen branding={branding} busy />\n }\n\n return (\n <Box key={turn} sx={{ position: 'relative', minHeight: '100dvh' }}>\n {offline ? (\n <Alert severity=\"warning\" sx={{ position: 'fixed', top: 0, left: 0, right: 0, zIndex: (theme) => theme.zIndex.modal + 1 }}>\n {'Reconnecting…'}\n </Alert>\n ) : null}\n {screen}\n <PosItemDialog\n product={itemProduct ? kioskItemProduct(itemProduct) : null}\n onClose={() => setItemProduct(null)}\n onConfirm={(choice) => {\n const product = itemProduct\n setItemProduct(null)\n if (product) addChoice(product, choice)\n }}\n formatMoney={money}\n blockSoldOut\n maxQuantity={CommerceModel.POS_KIOSK_MAX_QUANTITY}\n />\n <Dialog open={idle.warning !== null} onClose={idle.stillHere} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Still there?'}</DialogTitle>\n <DialogContent>\n <DialogContentText>\n {`This order will be cleared in ${idle.warning ?? 0} seconds.`}\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={reset}>{'Start over'}</Button>\n <Button variant=\"contained\" onClick={idle.stillHere}>\n {'I’m still here'}\n </Button>\n </DialogActions>\n </Dialog>\n {phase.kind === 'start' || phase.kind === 'menu' ? (\n <KioskStaffControl token={token} onExit={unpaired} onUnauthorized={unpaired} />\n ) : null}\n </Box>\n )\n}\n\nPosKioskPage.displayName = 'PosKioskPage'\n"],"names":["Alert","Box","Button","CircularProgress","Container","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Stack","useCallback","useEffect","useMemo","useRef","useState","CommerceModel","newAttemptKey","posNativeBridge","PosItemDialog","posItemNeedsChoice","PosDisplayBrandMark","PosDisplayBrandScreen","PosDisplayPairingScreen","displayMoney","PosDisplayReceiptScreen","PosDisplayTipScreen","posDisplayTouchSx","KioskDone","KioskPaying","KioskReview","KioskMenu","KioskStaffControl","clearKioskCustomerStorage","kioskApi","readKioskToken","storeKioskToken","useKioskIdle","POS_KIOSK_PAYMENT_POLL_MS","kioskItemProduct","product","$id","id","name","slug","type","status","options","modifierGroups","variants","map","variant","priceUsd","priceCents","inventory","soldOut","kioskCartLine","choice","find","candidate","picked","modifiers","pick","group","groupId","option","optionId","filter","Boolean","label","lineLabelWithModifiers","Object","keys","length","values","join","undefined","key","modifierSelectionKey","productId","variantId","quantity","Math","min","POS_KIOSK_MAX_QUANTITY","unitCents","reduce","sum","modifierOptionPriceCents","PosKioskPage","_props","context","idle","token","setToken","setContext","catalog","setCatalog","catalogLoading","setCatalogLoading","categoryId","setCategoryId","phase","setPhase","kind","lines","setLines","itemProduct","setItemProduct","cartOpen","setCartOpen","sale","setSale","tip","setTip","tipChoice","busy","setBusy","notice","setNotice","offline","setOffline","turn","setTurn","checkoutKey","payKey","saleRef","current","phaseRef","unpaired","lost","refresh","result","ok","value","timer","setInterval","clearInterval","active","then","currency","money","cents","reset","open","abandon","orderId","idleSeconds","POS_KIOSK_IDLE_SECONDS_DEFAULT","warningSeconds","POS_KIOSK_IDLE_WARNING_SECONDS","onExpire","setTimeout","POS_KIOSK_DONE_SECONDS","clearTimeout","addChoice","line","existing","POS_KIOSK_MAX_LINES","tapProduct","asItem","checkout","error","backToMenu","sendToCounter","counter","startPayment","method","answer","pay","next","paymentId","clientSecret","paymentIntentId","tipCents","posKioskTipCents","baseCents","dueCents","enabled","percentages","tipping","percent","tipPercent","chargeCents","failure","bridge","collected","collectCardPayment","amountCents","catch","message","paymentFailed","paymentStatus","payment","failureMessage","cancelPayment","fresh","answerReceipt","paid","receiptChannel","receipt","channel","email","to","phone","marketingOptIn","reader","payments","cardPresent","tap","payAtCounter","choosePay","sx","minHeight","display","placeItems","aria-label","mode","onPaired","branding","screen","size","onClick","theme","px","severity","onClose","m","mb","loading","onCategory","onProduct","onReview","onQuantity","onCartOpen","onPay","onCounter","onBack","maxWidth","py","spacing","alignItems","allowCustom","promptId","onAnswer","disabled","testMode","onCancel","onRetry","onSimulate","simulate","channels","receipts","offerMarketing","onDone","position","top","left","right","zIndex","modal","onConfirm","formatMoney","blockSoldOut","maxQuantity","warning","stillHere","fullWidth","onExit","onUnauthorized","displayName"],"mappings":"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"}
|
|
@@ -158,7 +158,7 @@ import { PosOfflineBanner, PosOfflineCheckout, usePosOffline } from "./pos-offli
|
|
|
158
158
|
/** The basket line an item-sheet choice makes: label and estimate from the product. */ export function registerLineFor(product, choice) {
|
|
159
159
|
var _variant_options, _variant_options1;
|
|
160
160
|
const { variant, modifiers, quantity } = choice;
|
|
161
|
-
const resolved = CommerceModel.resolveLineModifiers(product, modifiers);
|
|
161
|
+
const resolved = CommerceModel.resolveLineModifiers(product, modifiers, variant == null ? void 0 : variant.id);
|
|
162
162
|
const picked = resolved.ok ? resolved.modifiers : [];
|
|
163
163
|
const label = CommerceModel.lineLabelWithModifiers(Object.keys((_variant_options = variant.options) != null ? _variant_options : {}).length ? Object.values((_variant_options1 = variant.options) != null ? _variant_options1 : {}).join(' / ') : undefined, picked);
|
|
164
164
|
return _extends({
|