@aglyn/plugins-commerce 1.0.0-beta.232 → 1.0.0-beta.233

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/package.json +13 -13
  2. package/src/lib/components/cart-extras.d.ts +6 -0
  3. package/src/lib/components/cart-extras.js +4 -1
  4. package/src/lib/components/cart-extras.js.map +1 -1
  5. package/src/lib/components/cart-fulfillment.d.ts +117 -0
  6. package/src/lib/components/cart-fulfillment.js +367 -0
  7. package/src/lib/components/cart-fulfillment.js.map +1 -0
  8. package/src/lib/components/cart.js +52 -10
  9. package/src/lib/components/cart.js.map +1 -1
  10. package/src/lib/components/commerce-console-page.js +42 -1
  11. package/src/lib/components/commerce-console-page.js.map +1 -1
  12. package/src/lib/components/console/host-orders-card.component.js +38 -10
  13. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  14. package/src/lib/components/console/local-delivery-settings-card.component.d.ts +37 -0
  15. package/src/lib/components/console/local-delivery-settings-card.component.js +542 -0
  16. package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -0
  17. package/src/lib/components/console/locations-card.component.js +177 -3
  18. package/src/lib/components/console/locations-card.component.js.map +1 -1
  19. package/src/lib/components/console/order-detail-dialog.component.js +10 -0
  20. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  21. package/src/lib/components/console/order-local-fulfillment-panel.component.d.ts +44 -0
  22. package/src/lib/components/console/order-local-fulfillment-panel.component.js +265 -0
  23. package/src/lib/components/console/order-local-fulfillment-panel.component.js.map +1 -0
  24. package/src/lib/components/console/order-offline-notice.component.d.ts +12 -0
  25. package/src/lib/components/console/order-offline-notice.component.js +53 -0
  26. package/src/lib/components/console/order-offline-notice.component.js.map +1 -0
  27. package/src/lib/components/console/pickup-delivery-queue-card.component.d.ts +35 -0
  28. package/src/lib/components/console/pickup-delivery-queue-card.component.js +222 -0
  29. package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -0
  30. package/src/lib/components/console/pos/pos-api.d.ts +24 -1
  31. package/src/lib/components/console/pos/pos-api.js +13 -0
  32. package/src/lib/components/console/pos/pos-api.js.map +1 -1
  33. package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +12 -0
  34. package/src/lib/components/console/pos/pos-item-dialog.component.js +10 -8
  35. package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
  36. package/src/lib/components/console/pos/pos-kiosk-queue.component.d.ts +22 -0
  37. package/src/lib/components/console/pos/pos-kiosk-queue.component.js +168 -0
  38. package/src/lib/components/console/pos/pos-kiosk-queue.component.js.map +1 -0
  39. package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +18 -0
  40. package/src/lib/components/console/pos/pos-tender-dialogs.component.js +116 -1
  41. package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -1
  42. package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +8 -0
  43. package/src/lib/components/console/pos/pos-tender-panel.component.js +77 -18
  44. package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
  45. package/src/lib/components/console/pos/use-pos-display.d.ts +5 -2
  46. package/src/lib/components/console/pos/use-pos-display.js +3 -2
  47. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  48. package/src/lib/components/console/pos-devices-card.component.js +2 -2
  49. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  50. package/src/lib/components/console/pos-display/pairing-screen.d.ts +5 -2
  51. package/src/lib/components/console/pos-display/pairing-screen.js +7 -5
  52. package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -1
  53. package/src/lib/components/console/pos-display/pos-display-api.d.ts +7 -1
  54. package/src/lib/components/console/pos-display/pos-display-api.js +7 -2
  55. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  56. package/src/lib/components/console/pos-kiosk/kiosk-checkout.d.ts +41 -0
  57. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js +275 -0
  58. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js.map +1 -0
  59. package/src/lib/components/console/pos-kiosk/kiosk-menu.d.ts +32 -0
  60. package/src/lib/components/console/pos-kiosk/kiosk-menu.js +344 -0
  61. package/src/lib/components/console/pos-kiosk/kiosk-menu.js.map +1 -0
  62. package/src/lib/components/console/pos-kiosk/kiosk-staff.d.ts +12 -0
  63. package/src/lib/components/console/pos-kiosk/kiosk-staff.js +257 -0
  64. package/src/lib/components/console/pos-kiosk/kiosk-staff.js.map +1 -0
  65. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.d.ts +114 -0
  66. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js +189 -0
  67. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js.map +1 -0
  68. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.d.ts +16 -0
  69. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js +80 -0
  70. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js.map +1 -0
  71. package/src/lib/components/console/pos-kiosk-page.component.d.ts +28 -0
  72. package/src/lib/components/console/pos-kiosk-page.component.js +791 -0
  73. package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -0
  74. package/src/lib/components/console/pos-offline/pos-offline-api.d.ts +44 -0
  75. package/src/lib/components/console/pos-offline/pos-offline-api.js +69 -0
  76. package/src/lib/components/console/pos-offline/pos-offline-api.js.map +1 -0
  77. package/src/lib/components/console/pos-offline/pos-offline-banner.component.d.ts +7 -0
  78. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js +135 -0
  79. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js.map +1 -0
  80. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.d.ts +32 -0
  81. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js +287 -0
  82. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js.map +1 -0
  83. package/src/lib/components/console/pos-offline/pos-offline-store.d.ts +63 -0
  84. package/src/lib/components/console/pos-offline/pos-offline-store.js +145 -0
  85. package/src/lib/components/console/pos-offline/pos-offline-store.js.map +1 -0
  86. package/src/lib/components/console/pos-offline/register-offline.d.ts +24 -0
  87. package/src/lib/components/console/pos-offline/register-offline.js +24 -0
  88. package/src/lib/components/console/pos-offline/register-offline.js.map +1 -0
  89. package/src/lib/components/console/pos-offline/use-pos-offline.d.ts +85 -0
  90. package/src/lib/components/console/pos-offline/use-pos-offline.js +542 -0
  91. package/src/lib/components/console/pos-offline/use-pos-offline.js.map +1 -0
  92. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +72 -17
  93. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -1
  94. package/src/lib/components/console/pos-page.component.js +174 -27
  95. package/src/lib/components/console/pos-page.component.js.map +1 -1
  96. package/src/lib/components/console/products-hub-card.component.js +35 -10
  97. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  98. package/src/lib/components/console/shipping-settings-card.component.js +1 -1
  99. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
  100. package/src/lib/components/console/stock-movements-card.component.js +48 -16
  101. package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
  102. package/src/lib/components/console/store-zones.d.ts +8 -1
  103. package/src/lib/components/console/store-zones.js +11 -1
  104. package/src/lib/components/console/store-zones.js.map +1 -1
  105. package/src/lib/components/order-status.js +66 -0
  106. package/src/lib/components/order-status.js.map +1 -1
  107. package/src/lib/components/product-detail.js +42 -15
  108. package/src/lib/components/product-detail.js.map +1 -1
  109. package/src/lib/constants/local-fulfillment-list-query.d.ts +48 -0
  110. package/src/lib/constants/local-fulfillment-list-query.js +84 -0
  111. package/src/lib/constants/local-fulfillment-list-query.js.map +1 -0
  112. package/src/lib/constants/orders-list-query.d.ts +7 -2
  113. package/src/lib/constants/orders-list-query.js +89 -8
  114. package/src/lib/constants/orders-list-query.js.map +1 -1
  115. package/src/lib/constants/pos-shift-list-query.d.ts +22 -0
  116. package/src/lib/constants/pos-shift-list-query.js +115 -0
  117. package/src/lib/constants/pos-shift-list-query.js.map +1 -0
  118. package/src/lib/constants/product-list-query.d.ts +6 -1
  119. package/src/lib/constants/product-list-query.js +77 -8
  120. package/src/lib/constants/product-list-query.js.map +1 -1
  121. package/src/lib/constants/stock-movement-query.d.ts +3 -2
  122. package/src/lib/constants/stock-movement-query.js +52 -8
  123. package/src/lib/constants/stock-movement-query.js.map +1 -1
  124. package/src/lib/model/buyer-notifications.d.ts +5 -3
  125. package/src/lib/model/buyer-notifications.js +25 -4
  126. package/src/lib/model/buyer-notifications.js.map +1 -1
  127. package/src/lib/model/commerce-orders.d.ts +59 -0
  128. package/src/lib/model/commerce-orders.js.map +1 -1
  129. package/src/lib/model/commerce-pos-kiosk.d.ts +175 -0
  130. package/src/lib/model/commerce-pos-kiosk.js +147 -0
  131. package/src/lib/model/commerce-pos-kiosk.js.map +1 -0
  132. package/src/lib/model/commerce-pos-offline.d.ts +234 -0
  133. package/src/lib/model/commerce-pos-offline.js +301 -0
  134. package/src/lib/model/commerce-pos-offline.js.map +1 -0
  135. package/src/lib/model/commerce-pos-ops.d.ts +16 -6
  136. package/src/lib/model/commerce-pos-ops.js +12 -4
  137. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  138. package/src/lib/model/commerce-pos.d.ts +13 -1
  139. package/src/lib/model/commerce-pos.js +5 -4
  140. package/src/lib/model/commerce-pos.js.map +1 -1
  141. package/src/lib/model/commerce-stock-holds.d.ts +24 -3
  142. package/src/lib/model/commerce-stock-holds.js +26 -8
  143. package/src/lib/model/commerce-stock-holds.js.map +1 -1
  144. package/src/lib/model/commerce.d.ts +3 -0
  145. package/src/lib/model/commerce.js.map +1 -1
  146. package/src/lib/model/index.d.ts +4 -0
  147. package/src/lib/model/index.js +4 -0
  148. package/src/lib/model/index.js.map +1 -1
  149. package/src/lib/model/local-fulfillment-settings.d.ts +178 -0
  150. package/src/lib/model/local-fulfillment-settings.js +361 -0
  151. package/src/lib/model/local-fulfillment-settings.js.map +1 -0
  152. package/src/lib/model/order-list-fields.d.ts +10 -1
  153. package/src/lib/model/order-list-fields.js +1 -0
  154. package/src/lib/model/order-list-fields.js.map +1 -1
  155. package/src/lib/model/order-local-fulfillment.d.ts +131 -0
  156. package/src/lib/model/order-local-fulfillment.js +125 -0
  157. package/src/lib/model/order-local-fulfillment.js.map +1 -0
  158. package/src/lib/model/order-shipping-export.js +4 -0
  159. package/src/lib/model/order-shipping-export.js.map +1 -1
  160. package/src/lib/model/order-status-view.d.ts +20 -1
  161. package/src/lib/model/order-status-view.js +60 -6
  162. package/src/lib/model/order-status-view.js.map +1 -1
  163. package/src/lib/plugin-config.js +6 -2
  164. package/src/lib/plugin-config.js.map +1 -1
  165. package/src/lib/plugin.js +8 -0
  166. package/src/lib/plugin.js.map +1 -1
  167. package/src/lib/pos-kiosk-config.d.ts +26 -0
  168. package/src/lib/pos-kiosk-config.js +59 -0
  169. package/src/lib/pos-kiosk-config.js.map +1 -0
  170. package/src/lib/server/api-v1/openapi.js +8 -0
  171. package/src/lib/server/api-v1/openapi.js.map +1 -1
  172. package/src/lib/server/api-v1/order-view.d.ts +19 -0
  173. package/src/lib/server/api-v1/order-view.js +35 -0
  174. package/src/lib/server/api-v1/order-view.js.map +1 -1
  175. package/src/lib/server/billing-webhook.js +238 -87
  176. package/src/lib/server/billing-webhook.js.map +1 -1
  177. package/src/lib/server/cart-checkout.d.ts +2 -0
  178. package/src/lib/server/cart-checkout.js +173 -13
  179. package/src/lib/server/cart-checkout.js.map +1 -1
  180. package/src/lib/server/checkout-extras.js +18 -4
  181. package/src/lib/server/checkout-extras.js.map +1 -1
  182. package/src/lib/server/checkout.js +71 -14
  183. package/src/lib/server/checkout.js.map +1 -1
  184. package/src/lib/server/local-fulfillment-status.d.ts +86 -0
  185. package/src/lib/server/local-fulfillment-status.js +379 -0
  186. package/src/lib/server/local-fulfillment-status.js.map +1 -0
  187. package/src/lib/server/local-fulfillment.d.ts +190 -0
  188. package/src/lib/server/local-fulfillment.js +580 -0
  189. package/src/lib/server/local-fulfillment.js.map +1 -0
  190. package/src/lib/server/membership-register.js +3 -1
  191. package/src/lib/server/membership-register.js.map +1 -1
  192. package/src/lib/server/order-notifications.js +61 -0
  193. package/src/lib/server/order-notifications.js.map +1 -1
  194. package/src/lib/server/pos-display.d.ts +27 -1
  195. package/src/lib/server/pos-display.js +50 -9
  196. package/src/lib/server/pos-display.js.map +1 -1
  197. package/src/lib/server/pos-kiosk-principal.d.ts +29 -0
  198. package/src/lib/server/pos-kiosk-principal.js +42 -0
  199. package/src/lib/server/pos-kiosk-principal.js.map +1 -0
  200. package/src/lib/server/pos-kiosk.d.ts +54 -0
  201. package/src/lib/server/pos-kiosk.js +972 -0
  202. package/src/lib/server/pos-kiosk.js.map +1 -0
  203. package/src/lib/server/pos-offline-sync.d.ts +85 -0
  204. package/src/lib/server/pos-offline-sync.js +765 -0
  205. package/src/lib/server/pos-offline-sync.js.map +1 -0
  206. package/src/lib/server/pos-order.js +22 -4
  207. package/src/lib/server/pos-order.js.map +1 -1
  208. package/src/lib/server/pos-payment.d.ts +6 -0
  209. package/src/lib/server/pos-payment.js +225 -6
  210. package/src/lib/server/pos-payment.js.map +1 -1
  211. package/src/lib/server/pos-print.js +5 -0
  212. package/src/lib/server/pos-print.js.map +1 -1
  213. package/src/lib/server/pos-return.js +27 -0
  214. package/src/lib/server/pos-return.js.map +1 -1
  215. package/src/lib/server/pos-sale.d.ts +6 -0
  216. package/src/lib/server/pos-sale.js +2 -0
  217. package/src/lib/server/pos-sale.js.map +1 -1
  218. package/src/lib/server/pos-shift.js +8 -1
  219. package/src/lib/server/pos-shift.js.map +1 -1
  220. package/src/lib/server/refund.js +3 -0
  221. package/src/lib/server/refund.js.map +1 -1
  222. package/src/lib/server/stock-hold.d.ts +9 -1
  223. package/src/lib/server/stock-hold.js +15 -7
  224. package/src/lib/server/stock-hold.js.map +1 -1
  225. package/src/lib/server.js +16 -0
  226. package/src/lib/server.js.map +1 -1
  227. package/src/lib/tenant-emails.js +161 -0
  228. package/src/lib/tenant-emails.js.map +1 -1
@@ -1,3 +1,4 @@
1
+ import { type PosCreditAccount } from './pos-api';
1
2
  /** Cash: what the customer handed over, with one-tap round-ups. */
2
3
  export declare function PosCashDialog(props: {
3
4
  open: boolean;
@@ -51,3 +52,20 @@ export declare function PosKeyedCardDialog(props: {
51
52
  onClose: () => void;
52
53
  onConfirmed: () => void;
53
54
  }): import("react").JSX.Element;
55
+ /**
56
+ * Store credit another plugin keeps (AGL-3640) — a rewards balance, a friend's
57
+ * referral credit. The cashier finds the customer by email or code and takes
58
+ * from the account found, or applies a code the customer reads out. Which
59
+ * plugin answers is the provider's business; the register only shows its name
60
+ * and what the account can give.
61
+ */
62
+ export declare function PosCreditDialog(props: {
63
+ open: boolean;
64
+ label: string;
65
+ canLookup: boolean;
66
+ busy: boolean;
67
+ onClose: () => void;
68
+ onLookup: (query: string) => Promise<PosCreditAccount[] | null>;
69
+ onApplyCode: (code: string) => void;
70
+ onApplyAccount: (account: PosCreditAccount) => void;
71
+ }): import("react").JSX.Element;
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
17
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
18
- import { Alert, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, MenuItem, Stack, TextField, Typography } from "@mui/material";
18
+ import { Alert, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, List, ListItemButton, ListItemText, MenuItem, Stack, TextField, Typography } from "@mui/material";
19
19
  import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";
20
20
  // `/pure`: the Stripe script loads when a typed card is actually taken, not
21
21
  // whenever the register mounts (the AGL-2486 reasoning).
@@ -441,5 +441,120 @@ function KeyedCardForm(props) {
441
441
  ]
442
442
  });
443
443
  }
444
+ /**
445
+ * Store credit another plugin keeps (AGL-3640) — a rewards balance, a friend's
446
+ * referral credit. The cashier finds the customer by email or code and takes
447
+ * from the account found, or applies a code the customer reads out. Which
448
+ * plugin answers is the provider's business; the register only shows its name
449
+ * and what the account can give.
450
+ */ export function PosCreditDialog(props) {
451
+ const [query, setQuery] = useState('');
452
+ const [found, setFound] = useState(null);
453
+ const close = ()=>{
454
+ setQuery('');
455
+ setFound(null);
456
+ props.onClose();
457
+ };
458
+ const find = async ()=>{
459
+ if (!query.trim()) return;
460
+ setFound(await props.onLookup(query.trim()));
461
+ };
462
+ return /*#__PURE__*/ _jsxs(Dialog, {
463
+ open: props.open,
464
+ onClose: close,
465
+ maxWidth: "xs",
466
+ fullWidth: true,
467
+ children: [
468
+ /*#__PURE__*/ _jsx(DialogTitle, {
469
+ children: props.label
470
+ }),
471
+ /*#__PURE__*/ _jsxs(DialogContent, {
472
+ sx: {
473
+ display: 'flex',
474
+ flexDirection: 'column',
475
+ gap: 2
476
+ },
477
+ children: [
478
+ /*#__PURE__*/ _jsx(TextField, {
479
+ label: props.canLookup ? 'Code or customer email' : 'Code',
480
+ value: query,
481
+ onChange: (event)=>{
482
+ setQuery(event.target.value);
483
+ setFound(null);
484
+ },
485
+ onKeyDown: (event)=>{
486
+ if (event.key === 'Enter' && props.canLookup) void find();
487
+ },
488
+ autoFocus: true,
489
+ sx: {
490
+ mt: 1
491
+ },
492
+ slotProps: {
493
+ htmlInput: {
494
+ autoComplete: 'off',
495
+ 'data-testid': 'pos-credit-query'
496
+ }
497
+ }
498
+ }),
499
+ found && !found.length ? /*#__PURE__*/ _jsx(Alert, {
500
+ severity: "info",
501
+ children: 'No account matches.'
502
+ }) : null,
503
+ (found == null ? void 0 : found.length) ? /*#__PURE__*/ _jsx(List, {
504
+ disablePadding: true,
505
+ children: found.map((account)=>/*#__PURE__*/ _jsx(ListItemButton, {
506
+ disabled: props.busy || account.availableCents <= 0,
507
+ onClick: ()=>{
508
+ props.onApplyAccount(account);
509
+ setQuery('');
510
+ setFound(null);
511
+ },
512
+ divider: true,
513
+ sx: {
514
+ minHeight: POS_TOUCH_PX
515
+ },
516
+ children: /*#__PURE__*/ _jsx(ListItemText, {
517
+ primary: `${account.label}${account.last4 ? ` •• ${account.last4}` : ''} · ${usd(account.availableCents)} available`,
518
+ secondary: account.detail
519
+ })
520
+ }, account.reference))
521
+ }) : null
522
+ ]
523
+ }),
524
+ /*#__PURE__*/ _jsxs(DialogActions, {
525
+ children: [
526
+ /*#__PURE__*/ _jsx(Button, {
527
+ onClick: close,
528
+ sx: {
529
+ minHeight: POS_TOUCH_PX
530
+ },
531
+ children: 'Cancel'
532
+ }),
533
+ props.canLookup ? /*#__PURE__*/ _jsx(Button, {
534
+ disabled: props.busy || !query.trim(),
535
+ onClick: ()=>void find(),
536
+ sx: {
537
+ minHeight: POS_TOUCH_PX
538
+ },
539
+ children: 'Find'
540
+ }) : null,
541
+ /*#__PURE__*/ _jsx(Button, {
542
+ variant: "contained",
543
+ disabled: props.busy || !query.trim() || query.includes('@'),
544
+ onClick: ()=>{
545
+ props.onApplyCode(query.trim());
546
+ setQuery('');
547
+ setFound(null);
548
+ },
549
+ sx: {
550
+ minHeight: POS_TOUCH_PX
551
+ },
552
+ children: 'Apply code'
553
+ })
554
+ ]
555
+ })
556
+ ]
557
+ });
558
+ }
444
559
 
445
560
  //# sourceMappingURL=pos-tender-dialogs.component.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos/pos-tender-dialogs.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 Alert,\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'\n// `/pure`: the Stripe script loads when a typed card is actually taken, not\n// whenever the register mounts (the AGL-2486 reasoning).\nimport { loadStripe } from '@stripe/stripe-js/pure'\nimport type { Stripe } from '@stripe/stripe-js'\nimport { QRCodeSVG } from 'qrcode.react'\nimport { useMemo, useState } from 'react'\nimport { centsFromInput, usd } from './pos-api'\nimport { POS_TOUCH_PX } from './pos-product-grid.component'\n\n/*==========================================\n * The register's tender dialogs (AGL-3607). Each collects what its tender\n * needs and hands it to the tender panel, which owns the request.\n *=========================================*/\n\n/** Cash: what the customer handed over, with one-tap round-ups. */\nexport function PosCashDialog(props: {\n open: boolean\n dueCents: number\n tipCents: number\n busy: boolean\n onClose: () => void\n onTake: (tenderedCents: number) => void\n}) {\n const [received, setReceived] = useState('')\n const owed = props.dueCents + props.tipCents\n const tendered = centsFromInput(received)\n const quick = [...new Set([owed, Math.ceil(owed / 500) * 500, Math.ceil(owed / 1000) * 1000, Math.ceil(owed / 2000) * 2000])]\n .filter((value) => value >= owed)\n .slice(0, 4)\n const close = () => {\n setReceived('')\n props.onClose()\n }\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Cash — ${usd(owed)}`}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label=\"Cash received ($)\"\n value={received}\n onChange={(event) => setReceived(event.target.value.replace(/[^0-9.]/g, ''))}\n autoFocus\n sx={{ mt: 1 }}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap' }}>\n {quick.map((cents) => (\n <Button\n key={cents}\n variant=\"outlined\"\n onClick={() => setReceived((cents / 100).toFixed(2))}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {cents === owed ? 'Exact' : usd(cents)}\n </Button>\n ))}\n </Stack>\n {tendered > 0 && tendered >= owed ? (\n <Alert severity=\"success\">{`Change: ${usd(tendered - owed)}`}</Alert>\n ) : tendered > 0 && tendered < owed ? (\n <Alert severity=\"info\">\n {`Takes ${usd(Math.max(0, tendered - props.tipCents))} toward the sale; ${usd(owed - tendered)} left to pay.`}\n </Alert>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || tendered <= props.tipCents}\n onClick={() => {\n props.onTake(tendered)\n setReceived('')\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Take cash'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/** A gift card: type or scan the code, see the balance, apply it. */\nexport function PosGiftCardDialog(props: {\n open: boolean\n busy: boolean\n onClose: () => void\n onCheck: (code: string) => Promise<{ availableCents: number; frozen: boolean; voided: boolean } | null>\n onApply: (code: string) => void\n}) {\n const [code, setCode] = useState('')\n const [balance, setBalance] = useState<string | null>(null)\n const close = () => {\n setCode('')\n setBalance(null)\n props.onClose()\n }\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Gift card'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label=\"Gift card code\"\n value={code}\n onChange={(event) => {\n setCode(event.target.value.toUpperCase())\n setBalance(null)\n }}\n onKeyDown={async (event) => {\n if (event.key !== 'Enter' || !code.trim()) return\n const answer = await props.onCheck(code)\n setBalance(\n answer\n ? answer.frozen\n ? 'This card is on hold.'\n : answer.voided\n ? 'This card was voided.'\n : `Available: ${usd(answer.availableCents)}`\n : null,\n )\n }}\n autoFocus\n sx={{ mt: 1 }}\n slotProps={{ htmlInput: { autoComplete: 'off', autoCapitalize: 'characters' } }}\n />\n {balance ? <Alert severity=\"info\">{balance}</Alert> : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n disabled={!code.trim()}\n onClick={async () => {\n const answer = await props.onCheck(code)\n setBalance(\n answer\n ? answer.frozen\n ? 'This card is on hold.'\n : `Available: ${usd(answer.availableCents)}`\n : null,\n )\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Check balance'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || !code.trim()}\n onClick={() => {\n props.onApply(code)\n setCode('')\n setBalance(null)\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Apply card'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/** Charge to a checked-in stay's folio. */\nexport function PosFolioDialog(props: {\n open: boolean\n amountCents: number\n stays: any[]\n busy: boolean\n onClose: () => void\n onCharge: (reservationId: string) => void\n}) {\n const [stay, setStay] = useState('')\n return (\n <Dialog open={props.open} onClose={props.onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Charge to room — ${usd(props.amountCents)}`}</DialogTitle>\n <DialogContent>\n <TextField\n label=\"Checked-in stay\"\n value={stay}\n onChange={(event) => setStay(event.target.value)}\n select\n fullWidth\n sx={{ mt: 1 }}\n >\n {props.stays.map((entry: any) => (\n <MenuItem key={entry.$id} value={entry.$id}>\n {entry.guestName ?? entry.guestEmail ?? entry.$id}\n </MenuItem>\n ))}\n </TextField>\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || !stay}\n onClick={() => props.onCharge(stay)}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Charge folio'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/**\n * The QR payment page. Encoded in this browser, never fetched (AGL-1671): a\n * live payment URL in a third party's query string is a link that pays the\n * sale for whoever opens it.\n */\nexport function PosQrDialog(props: { url: string; amountCents: number; onClose: () => void }) {\n return (\n <Dialog open={Boolean(props.url)} onClose={props.onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Scan to pay ${usd(props.amountCents)}`}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 1 }}>\n {'The customer scans this and pays on their phone. The payment shows ' +\n 'here as soon as it goes through.'}\n </Typography>\n <Box sx={{ display: 'flex', justifyContent: 'center' }}>\n <QRCodeSVG value={props.url} size={256} level=\"L\" marginSize={4} title=\"Payment QR\" role=\"img\" />\n </Box>\n <Button href={props.url} target=\"_blank\" rel=\"noopener noreferrer\">\n {'Open payment page'}\n </Button>\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Close'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nconst stripePromises = new Map<string, Promise<Stripe | null>>()\n\nfunction stripeFor(publishableKey: string): Promise<Stripe | null> {\n let promise = stripePromises.get(publishableKey)\n if (!promise) {\n promise = loadStripe(publishableKey)\n stripePromises.set(publishableKey, promise)\n }\n return promise\n}\n\n/**\n * A card typed in by staff (card not present). The card goes into Stripe's\n * own Payment Element and never touches the register; the server created the\n * PaymentIntent and records the payment from Stripe, never from this form's\n * say-so.\n */\nexport function PosKeyedCardDialog(props: {\n clientSecret: string\n publishableKey: string\n amountCents: number\n onClose: () => void\n onConfirmed: () => void\n}) {\n const stripe = useMemo(\n () => (props.publishableKey ? stripeFor(props.publishableKey) : null),\n [props.publishableKey],\n )\n return (\n <Dialog open={Boolean(props.clientSecret)} onClose={props.onClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{`Type a card — ${usd(props.amountCents)}`}</DialogTitle>\n {props.clientSecret && stripe ? (\n <Elements stripe={stripe} options={{ clientSecret: props.clientSecret }}>\n <KeyedCardForm onClose={props.onClose} onConfirmed={props.onConfirmed} />\n </Elements>\n ) : null}\n </Dialog>\n )\n}\n\nfunction KeyedCardForm(props: { onClose: () => void; onConfirmed: () => void }) {\n const stripe = useStripe()\n const elements = useElements()\n const [error, setError] = useState('')\n const [busy, setBusy] = useState(false)\n return (\n <>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <PaymentElement options={{ layout: 'tabs', wallets: { applePay: 'never', googlePay: 'never' } }} />\n {error ? <Alert severity=\"error\">{error}</Alert> : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} disabled={busy} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={busy || !stripe || !elements}\n onClick={async () => {\n if (!stripe || !elements) return\n setBusy(true)\n setError('')\n const result = await stripe.confirmPayment({\n elements,\n redirect: 'if_required',\n confirmParams: { return_url: window.location.href },\n })\n setBusy(false)\n if (result.error) {\n setError(result.error.message ?? 'The card was not accepted.')\n return\n }\n props.onConfirmed()\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {busy ? 'Charging…' : 'Charge card'}\n </Button>\n </DialogActions>\n </>\n )\n}\n"],"names":["Alert","Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Typography","Elements","PaymentElement","useElements","useStripe","loadStripe","QRCodeSVG","useMemo","useState","centsFromInput","usd","POS_TOUCH_PX","PosCashDialog","props","received","setReceived","owed","dueCents","tipCents","tendered","quick","Set","Math","ceil","filter","value","slice","close","onClose","open","maxWidth","fullWidth","sx","display","flexDirection","gap","label","onChange","event","target","replace","autoFocus","mt","slotProps","htmlInput","inputMode","direction","spacing","flexWrap","map","cents","variant","onClick","toFixed","minHeight","severity","max","disabled","busy","onTake","PosGiftCardDialog","code","setCode","balance","setBalance","toUpperCase","onKeyDown","key","trim","answer","onCheck","frozen","voided","availableCents","autoComplete","autoCapitalize","onApply","PosFolioDialog","stay","setStay","amountCents","select","stays","entry","$id","guestName","guestEmail","onCharge","PosQrDialog","Boolean","url","color","justifyContent","size","level","marginSize","title","role","href","rel","stripePromises","Map","stripeFor","publishableKey","promise","get","set","PosKeyedCardDialog","stripe","clientSecret","options","KeyedCardForm","onConfirmed","elements","error","setError","setBusy","layout","wallets","applePay","googlePay","result","confirmPayment","redirect","confirmParams","return_url","window","location","message"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos/pos-tender-dialogs.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 Alert,\n Box,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n List,\n ListItemButton,\n ListItemText,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'\n// `/pure`: the Stripe script loads when a typed card is actually taken, not\n// whenever the register mounts (the AGL-2486 reasoning).\nimport { loadStripe } from '@stripe/stripe-js/pure'\nimport type { Stripe } from '@stripe/stripe-js'\nimport { QRCodeSVG } from 'qrcode.react'\nimport { useMemo, useState } from 'react'\nimport { centsFromInput, usd, type PosCreditAccount } from './pos-api'\nimport { POS_TOUCH_PX } from './pos-product-grid.component'\n\n/*==========================================\n * The register's tender dialogs (AGL-3607). Each collects what its tender\n * needs and hands it to the tender panel, which owns the request.\n *=========================================*/\n\n/** Cash: what the customer handed over, with one-tap round-ups. */\nexport function PosCashDialog(props: {\n open: boolean\n dueCents: number\n tipCents: number\n busy: boolean\n onClose: () => void\n onTake: (tenderedCents: number) => void\n}) {\n const [received, setReceived] = useState('')\n const owed = props.dueCents + props.tipCents\n const tendered = centsFromInput(received)\n const quick = [...new Set([owed, Math.ceil(owed / 500) * 500, Math.ceil(owed / 1000) * 1000, Math.ceil(owed / 2000) * 2000])]\n .filter((value) => value >= owed)\n .slice(0, 4)\n const close = () => {\n setReceived('')\n props.onClose()\n }\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Cash — ${usd(owed)}`}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label=\"Cash received ($)\"\n value={received}\n onChange={(event) => setReceived(event.target.value.replace(/[^0-9.]/g, ''))}\n autoFocus\n sx={{ mt: 1 }}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n <Stack direction=\"row\" spacing={1} sx={{ flexWrap: 'wrap' }}>\n {quick.map((cents) => (\n <Button\n key={cents}\n variant=\"outlined\"\n onClick={() => setReceived((cents / 100).toFixed(2))}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {cents === owed ? 'Exact' : usd(cents)}\n </Button>\n ))}\n </Stack>\n {tendered > 0 && tendered >= owed ? (\n <Alert severity=\"success\">{`Change: ${usd(tendered - owed)}`}</Alert>\n ) : tendered > 0 && tendered < owed ? (\n <Alert severity=\"info\">\n {`Takes ${usd(Math.max(0, tendered - props.tipCents))} toward the sale; ${usd(owed - tendered)} left to pay.`}\n </Alert>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || tendered <= props.tipCents}\n onClick={() => {\n props.onTake(tendered)\n setReceived('')\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Take cash'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/** A gift card: type or scan the code, see the balance, apply it. */\nexport function PosGiftCardDialog(props: {\n open: boolean\n busy: boolean\n onClose: () => void\n onCheck: (code: string) => Promise<{ availableCents: number; frozen: boolean; voided: boolean } | null>\n onApply: (code: string) => void\n}) {\n const [code, setCode] = useState('')\n const [balance, setBalance] = useState<string | null>(null)\n const close = () => {\n setCode('')\n setBalance(null)\n props.onClose()\n }\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Gift card'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label=\"Gift card code\"\n value={code}\n onChange={(event) => {\n setCode(event.target.value.toUpperCase())\n setBalance(null)\n }}\n onKeyDown={async (event) => {\n if (event.key !== 'Enter' || !code.trim()) return\n const answer = await props.onCheck(code)\n setBalance(\n answer\n ? answer.frozen\n ? 'This card is on hold.'\n : answer.voided\n ? 'This card was voided.'\n : `Available: ${usd(answer.availableCents)}`\n : null,\n )\n }}\n autoFocus\n sx={{ mt: 1 }}\n slotProps={{ htmlInput: { autoComplete: 'off', autoCapitalize: 'characters' } }}\n />\n {balance ? <Alert severity=\"info\">{balance}</Alert> : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n disabled={!code.trim()}\n onClick={async () => {\n const answer = await props.onCheck(code)\n setBalance(\n answer\n ? answer.frozen\n ? 'This card is on hold.'\n : `Available: ${usd(answer.availableCents)}`\n : null,\n )\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Check balance'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || !code.trim()}\n onClick={() => {\n props.onApply(code)\n setCode('')\n setBalance(null)\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Apply card'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/** Charge to a checked-in stay's folio. */\nexport function PosFolioDialog(props: {\n open: boolean\n amountCents: number\n stays: any[]\n busy: boolean\n onClose: () => void\n onCharge: (reservationId: string) => void\n}) {\n const [stay, setStay] = useState('')\n return (\n <Dialog open={props.open} onClose={props.onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Charge to room — ${usd(props.amountCents)}`}</DialogTitle>\n <DialogContent>\n <TextField\n label=\"Checked-in stay\"\n value={stay}\n onChange={(event) => setStay(event.target.value)}\n select\n fullWidth\n sx={{ mt: 1 }}\n >\n {props.stays.map((entry: any) => (\n <MenuItem key={entry.$id} value={entry.$id}>\n {entry.guestName ?? entry.guestEmail ?? entry.$id}\n </MenuItem>\n ))}\n </TextField>\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={props.busy || !stay}\n onClick={() => props.onCharge(stay)}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Charge folio'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\n/**\n * The QR payment page. Encoded in this browser, never fetched (AGL-1671): a\n * live payment URL in a third party's query string is a link that pays the\n * sale for whoever opens it.\n */\nexport function PosQrDialog(props: { url: string; amountCents: number; onClose: () => void }) {\n return (\n <Dialog open={Boolean(props.url)} onClose={props.onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Scan to pay ${usd(props.amountCents)}`}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 1 }}>\n {'The customer scans this and pays on their phone. The payment shows ' +\n 'here as soon as it goes through.'}\n </Typography>\n <Box sx={{ display: 'flex', justifyContent: 'center' }}>\n <QRCodeSVG value={props.url} size={256} level=\"L\" marginSize={4} title=\"Payment QR\" role=\"img\" />\n </Box>\n <Button href={props.url} target=\"_blank\" rel=\"noopener noreferrer\">\n {'Open payment page'}\n </Button>\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Close'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nconst stripePromises = new Map<string, Promise<Stripe | null>>()\n\nfunction stripeFor(publishableKey: string): Promise<Stripe | null> {\n let promise = stripePromises.get(publishableKey)\n if (!promise) {\n promise = loadStripe(publishableKey)\n stripePromises.set(publishableKey, promise)\n }\n return promise\n}\n\n/**\n * A card typed in by staff (card not present). The card goes into Stripe's\n * own Payment Element and never touches the register; the server created the\n * PaymentIntent and records the payment from Stripe, never from this form's\n * say-so.\n */\nexport function PosKeyedCardDialog(props: {\n clientSecret: string\n publishableKey: string\n amountCents: number\n onClose: () => void\n onConfirmed: () => void\n}) {\n const stripe = useMemo(\n () => (props.publishableKey ? stripeFor(props.publishableKey) : null),\n [props.publishableKey],\n )\n return (\n <Dialog open={Boolean(props.clientSecret)} onClose={props.onClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{`Type a card — ${usd(props.amountCents)}`}</DialogTitle>\n {props.clientSecret && stripe ? (\n <Elements stripe={stripe} options={{ clientSecret: props.clientSecret }}>\n <KeyedCardForm onClose={props.onClose} onConfirmed={props.onConfirmed} />\n </Elements>\n ) : null}\n </Dialog>\n )\n}\n\nfunction KeyedCardForm(props: { onClose: () => void; onConfirmed: () => void }) {\n const stripe = useStripe()\n const elements = useElements()\n const [error, setError] = useState('')\n const [busy, setBusy] = useState(false)\n return (\n <>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <PaymentElement options={{ layout: 'tabs', wallets: { applePay: 'never', googlePay: 'never' } }} />\n {error ? <Alert severity=\"error\">{error}</Alert> : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={props.onClose} disabled={busy} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={busy || !stripe || !elements}\n onClick={async () => {\n if (!stripe || !elements) return\n setBusy(true)\n setError('')\n const result = await stripe.confirmPayment({\n elements,\n redirect: 'if_required',\n confirmParams: { return_url: window.location.href },\n })\n setBusy(false)\n if (result.error) {\n setError(result.error.message ?? 'The card was not accepted.')\n return\n }\n props.onConfirmed()\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {busy ? 'Charging…' : 'Charge card'}\n </Button>\n </DialogActions>\n </>\n )\n}\n\n/**\n * Store credit another plugin keeps (AGL-3640) — a rewards balance, a friend's\n * referral credit. The cashier finds the customer by email or code and takes\n * from the account found, or applies a code the customer reads out. Which\n * plugin answers is the provider's business; the register only shows its name\n * and what the account can give.\n */\nexport function PosCreditDialog(props: {\n open: boolean\n label: string\n canLookup: boolean\n busy: boolean\n onClose: () => void\n onLookup: (query: string) => Promise<PosCreditAccount[] | null>\n onApplyCode: (code: string) => void\n onApplyAccount: (account: PosCreditAccount) => void\n}) {\n const [query, setQuery] = useState('')\n const [found, setFound] = useState<PosCreditAccount[] | null>(null)\n const close = () => {\n setQuery('')\n setFound(null)\n props.onClose()\n }\n const find = async () => {\n if (!query.trim()) return\n setFound(await props.onLookup(query.trim()))\n }\n return (\n <Dialog open={props.open} onClose={close} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{props.label}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <TextField\n label={props.canLookup ? 'Code or customer email' : 'Code'}\n value={query}\n onChange={(event) => {\n setQuery(event.target.value)\n setFound(null)\n }}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && props.canLookup) void find()\n }}\n autoFocus\n sx={{ mt: 1 }}\n slotProps={{ htmlInput: { autoComplete: 'off', 'data-testid': 'pos-credit-query' } }}\n />\n {found && !found.length ? <Alert severity=\"info\">{'No account matches.'}</Alert> : null}\n {found?.length ? (\n <List disablePadding>\n {found.map((account) => (\n <ListItemButton\n key={account.reference}\n disabled={props.busy || account.availableCents <= 0}\n onClick={() => {\n props.onApplyAccount(account)\n setQuery('')\n setFound(null)\n }}\n divider\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n <ListItemText\n primary={`${account.label}${account.last4 ? ` •• ${account.last4}` : ''} · ${usd(account.availableCents)} available`}\n secondary={account.detail}\n />\n </ListItemButton>\n ))}\n </List>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={close} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Cancel'}\n </Button>\n {props.canLookup ? (\n <Button disabled={props.busy || !query.trim()} onClick={() => void find()} sx={{ minHeight: POS_TOUCH_PX }}>\n {'Find'}\n </Button>\n ) : null}\n <Button\n variant=\"contained\"\n disabled={props.busy || !query.trim() || query.includes('@')}\n onClick={() => {\n props.onApplyCode(query.trim())\n setQuery('')\n setFound(null)\n }}\n sx={{ minHeight: POS_TOUCH_PX }}\n >\n {'Apply code'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n"],"names":["Alert","Box","Button","Dialog","DialogActions","DialogContent","DialogTitle","List","ListItemButton","ListItemText","MenuItem","Stack","TextField","Typography","Elements","PaymentElement","useElements","useStripe","loadStripe","QRCodeSVG","useMemo","useState","centsFromInput","usd","POS_TOUCH_PX","PosCashDialog","props","received","setReceived","owed","dueCents","tipCents","tendered","quick","Set","Math","ceil","filter","value","slice","close","onClose","open","maxWidth","fullWidth","sx","display","flexDirection","gap","label","onChange","event","target","replace","autoFocus","mt","slotProps","htmlInput","inputMode","direction","spacing","flexWrap","map","cents","variant","onClick","toFixed","minHeight","severity","max","disabled","busy","onTake","PosGiftCardDialog","code","setCode","balance","setBalance","toUpperCase","onKeyDown","key","trim","answer","onCheck","frozen","voided","availableCents","autoComplete","autoCapitalize","onApply","PosFolioDialog","stay","setStay","amountCents","select","stays","entry","$id","guestName","guestEmail","onCharge","PosQrDialog","Boolean","url","color","justifyContent","size","level","marginSize","title","role","href","rel","stripePromises","Map","stripeFor","publishableKey","promise","get","set","PosKeyedCardDialog","stripe","clientSecret","options","KeyedCardForm","onConfirmed","elements","error","setError","setBusy","layout","wallets","applePay","googlePay","result","confirmPayment","redirect","confirmParams","return_url","window","location","message","PosCreditDialog","query","setQuery","found","setFound","find","onLookup","canLookup","length","disablePadding","account","onApplyAccount","divider","primary","last4","secondary","detail","reference","includes","onApplyCode"],"mappings":"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"}
@@ -17,6 +17,14 @@ export interface PosTenderPanelProps {
17
17
  /** A PIN-switched cashier (AGL-3609) takes each payment they start. */
18
18
  cashierAssertion?: string;
19
19
  notify: (message: string, variant: 'success' | 'error' | 'warning' | 'info') => void;
20
+ /**
21
+ * The register is offline (AGL-3625). Every tender here is the server's —
22
+ * the card reader, the typed card, the QR link, the gift card, the room
23
+ * charge and this sale's own cash — so each is off until it returns.
24
+ */
25
+ offline?: boolean;
26
+ /** Rings this basket as an offline cash sale instead; offered while nothing is paid. */
27
+ onSellOffline?: () => void;
20
28
  }
21
29
  /**
22
30
  * Taking payment on an open sale (AGL-3607): the balance due, every payment
@@ -20,9 +20,9 @@ import { Alert, Box, Button, Chip, Divider, MenuItem, Stack, TextField, Typograp
20
20
  import { useConfirmationContext } from "@aglyn/shared-ui-jsx";
21
21
  import { useCallback, useEffect, useRef, useState } from "react";
22
22
  import * as CommerceModel from "../../../model/index.js";
23
- import { centsFromInput, newAttemptKey, posGiftCardBalance, posNativeBridge, posTender, PosRequestError, usd } from "./pos-api.js";
23
+ import { centsFromInput, newAttemptKey, posCreditLookup, posGiftCardBalance, posNativeBridge, posTender, PosRequestError, usd } from "./pos-api.js";
24
24
  import { POS_TOUCH_PX } from "./pos-product-grid.component.js";
25
- import { PosCashDialog, PosFolioDialog, PosGiftCardDialog, PosKeyedCardDialog, PosQrDialog } from "./pos-tender-dialogs.component.js";
25
+ import { PosCashDialog, PosCreditDialog, PosFolioDialog, PosGiftCardDialog, PosKeyedCardDialog, PosQrDialog } from "./pos-tender-dialogs.component.js";
26
26
  const STATUS_LABEL = {
27
27
  pending: 'Waiting',
28
28
  succeeded: 'Approved',
@@ -43,7 +43,7 @@ const STATUS_COLOR = {
43
43
  * payments as it needs; it is paid when the balance reaches zero, and only
44
44
  * then does the server take the stock and complete it.
45
45
  */ export function PosTenderPanel(props) {
46
- var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;
46
+ var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
47
47
  var _context_terminal, _context_terminal1;
48
48
  const { user, hostId, sale, context, display, onSale, notify } = props;
49
49
  const settings = context == null ? void 0 : context.settings;
@@ -51,6 +51,8 @@ const STATUS_COLOR = {
51
51
  const [tipCents, setTipCents] = useState(0);
52
52
  const [busy, setBusy] = useState(false);
53
53
  const [dialog, setDialog] = useState(null);
54
+ // The store-credit provider whose dialog is open (AGL-3640).
55
+ const [creditProvider, setCreditProvider] = useState(null);
54
56
  const [qr, setQr] = useState(null);
55
57
  const [keyed, setKeyed] = useState(null);
56
58
  const [readerId, setReaderId] = useState('');
@@ -80,6 +82,7 @@ const STATUS_COLOR = {
80
82
  const typedCents = centsFromInput(amount);
81
83
  const chargeCents = typedCents > 0 ? Math.min(typedCents, sale.tenderableCents) : sale.tenderableCents;
82
84
  const paid = sale.status === 'paid';
85
+ const offline = props.offline === true;
83
86
  const run = useCallback(async (action, body = {}, starts = false)=>{
84
87
  if (inFlight.current) return null;
85
88
  inFlight.current = true;
@@ -368,6 +371,16 @@ const STATUS_COLOR = {
368
371
  }, payment.id);
369
372
  })
370
373
  }) : null,
374
+ offline && !paid ? /*#__PURE__*/ _jsx(Alert, {
375
+ severity: "warning",
376
+ action: props.onSellOffline && sale.payments.length === 0 ? /*#__PURE__*/ _jsx(Button, {
377
+ color: "inherit",
378
+ size: "small",
379
+ onClick: props.onSellOffline,
380
+ children: 'Sell for cash offline'
381
+ }) : null,
382
+ children: sale.payments.length === 0 ? 'Offline: card readers, typed cards, the QR link, gift cards, store credit and room charges are off. ' + 'Take this basket as an offline cash sale, or wait for the connection.' : 'Offline: this sale has a payment on it and finishes when the connection returns. ' + 'Card readers, typed cards, the QR link, gift cards, store credit and room charges are off.'
383
+ }) : null,
371
384
  !paid ? /*#__PURE__*/ _jsxs(_Fragment, {
372
385
  children: [
373
386
  /*#__PURE__*/ _jsx(Divider, {}),
@@ -412,7 +425,7 @@ const STATUS_COLOR = {
412
425
  display.connected ? /*#__PURE__*/ _jsx(Button, {
413
426
  variant: "outlined",
414
427
  onClick: ()=>void askTip(),
415
- disabled: busy || Boolean(display.asking),
428
+ disabled: offline || busy || Boolean(display.asking),
416
429
  sx: {
417
430
  minHeight: POS_TOUCH_PX
418
431
  },
@@ -444,7 +457,7 @@ const STATUS_COLOR = {
444
457
  children: [
445
458
  /*#__PURE__*/ _jsx(Button, {
446
459
  variant: "contained",
447
- disabled: busy || chargeCents <= 0,
460
+ disabled: offline || busy || chargeCents <= 0,
448
461
  onClick: ()=>setDialog('cash'),
449
462
  sx: {
450
463
  minHeight: 56
@@ -453,7 +466,7 @@ const STATUS_COLOR = {
453
466
  }),
454
467
  (context == null ? void 0 : (_context_terminal = context.terminal) == null ? void 0 : _context_terminal.available) && readers.length ? /*#__PURE__*/ _jsx(Button, {
455
468
  variant: "contained",
456
- disabled: busy || chargeCents <= 0 || !readerId,
469
+ disabled: offline || busy || chargeCents <= 0 || !readerId,
457
470
  onClick: ()=>void startCardPresent(),
458
471
  sx: {
459
472
  minHeight: 56
@@ -462,7 +475,7 @@ const STATUS_COLOR = {
462
475
  }) : null,
463
476
  posNativeBridge() ? /*#__PURE__*/ _jsx(Button, {
464
477
  variant: "contained",
465
- disabled: busy || chargeCents <= 0,
478
+ disabled: offline || busy || chargeCents <= 0,
466
479
  onClick: ()=>void startBridge(),
467
480
  sx: {
468
481
  minHeight: 56
@@ -471,7 +484,7 @@ const STATUS_COLOR = {
471
484
  }) : null,
472
485
  (context == null ? void 0 : context.publishableKey) ? /*#__PURE__*/ _jsx(Button, {
473
486
  variant: "outlined",
474
- disabled: busy || chargeCents <= 0,
487
+ disabled: offline || busy || chargeCents <= 0,
475
488
  onClick: ()=>void startKeyed(),
476
489
  sx: {
477
490
  minHeight: 56
@@ -480,7 +493,7 @@ const STATUS_COLOR = {
480
493
  }) : null,
481
494
  /*#__PURE__*/ _jsx(Button, {
482
495
  variant: "outlined",
483
- disabled: busy || chargeCents <= 0,
496
+ disabled: offline || busy || chargeCents <= 0,
484
497
  onClick: ()=>void startLink(),
485
498
  sx: {
486
499
  minHeight: 56
@@ -489,16 +502,28 @@ const STATUS_COLOR = {
489
502
  }),
490
503
  /*#__PURE__*/ _jsx(Button, {
491
504
  variant: "outlined",
492
- disabled: busy || chargeCents <= 0,
505
+ disabled: offline || busy || chargeCents <= 0,
493
506
  onClick: ()=>setDialog('gift'),
494
507
  sx: {
495
508
  minHeight: 56
496
509
  },
497
510
  children: 'Gift card'
498
511
  }),
512
+ ((_ref2 = context == null ? void 0 : context.credits) != null ? _ref2 : []).map((credit)=>/*#__PURE__*/ _jsx(Button, {
513
+ variant: "outlined",
514
+ disabled: offline || busy || chargeCents <= 0,
515
+ onClick: ()=>{
516
+ setCreditProvider(credit);
517
+ setDialog('credit');
518
+ },
519
+ sx: {
520
+ minHeight: 56
521
+ },
522
+ children: credit.label
523
+ }, credit.providerId)),
499
524
  props.stays.length ? /*#__PURE__*/ _jsx(Button, {
500
525
  variant: "outlined",
501
- disabled: busy || chargeCents <= 0,
526
+ disabled: offline || busy || chargeCents <= 0,
502
527
  onClick: ()=>setDialog('folio'),
503
528
  sx: {
504
529
  minHeight: 56
@@ -524,11 +549,11 @@ const STATUS_COLOR = {
524
549
  }) : null,
525
550
  /*#__PURE__*/ _jsx(Button, {
526
551
  color: "error",
527
- disabled: busy,
552
+ disabled: offline || busy,
528
553
  onClick: async ()=>{
529
554
  const confirmed = await confirm({
530
555
  title: 'Void this sale?',
531
- description: 'Every payment taken on it is handed back: cards are refunded, gift ' + 'cards re-credited and room charges removed. Hand back any cash.',
556
+ description: 'Every payment taken on it is handed back: cards are refunded, gift ' + 'cards and store credit re-credited and room charges removed. Hand back any cash.',
532
557
  confirmationText: 'Void sale',
533
558
  confirmationButtonProps: {
534
559
  color: 'error'
@@ -592,6 +617,40 @@ const STATUS_COLOR = {
592
617
  if (result) setDialog(null);
593
618
  }
594
619
  }),
620
+ /*#__PURE__*/ _jsx(PosCreditDialog, {
621
+ open: dialog === 'credit' && Boolean(creditProvider),
622
+ label: (_ref3 = creditProvider == null ? void 0 : creditProvider.label) != null ? _ref3 : 'Store credit',
623
+ canLookup: Boolean(creditProvider == null ? void 0 : creditProvider.lookup),
624
+ busy: busy,
625
+ onClose: ()=>setDialog(null),
626
+ onLookup: async (query)=>{
627
+ if (!creditProvider) return null;
628
+ try {
629
+ return (await posCreditLookup(user, hostId, creditProvider.providerId, query)).accounts;
630
+ } catch (error) {
631
+ notify(error instanceof PosRequestError ? error.message : 'Could not look that up', 'warning');
632
+ return null;
633
+ }
634
+ },
635
+ onApplyCode: async (code)=>{
636
+ const result = await run('credit', _extends({
637
+ code
638
+ }, typedCents > 0 ? {
639
+ amountCents: chargeCents
640
+ } : {}), true);
641
+ if (result) setDialog(null);
642
+ },
643
+ onApplyAccount: async (account)=>{
644
+ if (!creditProvider) return;
645
+ const result = await run('credit', _extends({
646
+ providerId: creditProvider.providerId,
647
+ reference: account.reference
648
+ }, typedCents > 0 ? {
649
+ amountCents: chargeCents
650
+ } : {}), true);
651
+ if (result) setDialog(null);
652
+ }
653
+ }),
595
654
  /*#__PURE__*/ _jsx(PosFolioDialog, {
596
655
  open: dialog === 'folio',
597
656
  amountCents: chargeCents,
@@ -608,14 +667,14 @@ const STATUS_COLOR = {
608
667
  }
609
668
  }),
610
669
  /*#__PURE__*/ _jsx(PosQrDialog, {
611
- url: (_ref2 = qr == null ? void 0 : qr.url) != null ? _ref2 : '',
612
- amountCents: (_ref3 = qr == null ? void 0 : qr.amountCents) != null ? _ref3 : 0,
670
+ url: (_ref4 = qr == null ? void 0 : qr.url) != null ? _ref4 : '',
671
+ amountCents: (_ref5 = qr == null ? void 0 : qr.amountCents) != null ? _ref5 : 0,
613
672
  onClose: ()=>setQr(null)
614
673
  }),
615
674
  /*#__PURE__*/ _jsx(PosKeyedCardDialog, {
616
- clientSecret: (_ref4 = keyed == null ? void 0 : keyed.clientSecret) != null ? _ref4 : '',
617
- publishableKey: (_ref5 = context == null ? void 0 : context.publishableKey) != null ? _ref5 : '',
618
- amountCents: (_ref6 = keyed == null ? void 0 : keyed.amountCents) != null ? _ref6 : 0,
675
+ clientSecret: (_ref6 = keyed == null ? void 0 : keyed.clientSecret) != null ? _ref6 : '',
676
+ publishableKey: (_ref7 = context == null ? void 0 : context.publishableKey) != null ? _ref7 : '',
677
+ amountCents: (_ref8 = keyed == null ? void 0 : keyed.amountCents) != null ? _ref8 : 0,
619
678
  onClose: async ()=>{
620
679
  const open = keyed;
621
680
  setKeyed(null);