@aglyn/plugins-commerce 1.0.0-beta.231 → 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 (266) 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/catalog-organization-card.component.js +1 -0
  13. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -1
  14. package/src/lib/components/console/host-orders-card.component.js +42 -11
  15. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  16. package/src/lib/components/console/local-delivery-settings-card.component.d.ts +37 -0
  17. package/src/lib/components/console/local-delivery-settings-card.component.js +542 -0
  18. package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -0
  19. package/src/lib/components/console/locations-card.component.js +177 -3
  20. package/src/lib/components/console/locations-card.component.js.map +1 -1
  21. package/src/lib/components/console/order-detail-dialog.component.js +10 -0
  22. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  23. package/src/lib/components/console/order-local-fulfillment-panel.component.d.ts +44 -0
  24. package/src/lib/components/console/order-local-fulfillment-panel.component.js +265 -0
  25. package/src/lib/components/console/order-local-fulfillment-panel.component.js.map +1 -0
  26. package/src/lib/components/console/order-offline-notice.component.d.ts +12 -0
  27. package/src/lib/components/console/order-offline-notice.component.js +53 -0
  28. package/src/lib/components/console/order-offline-notice.component.js.map +1 -0
  29. package/src/lib/components/console/pickup-delivery-queue-card.component.d.ts +35 -0
  30. package/src/lib/components/console/pickup-delivery-queue-card.component.js +222 -0
  31. package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -0
  32. package/src/lib/components/console/pos/pos-api.d.ts +24 -1
  33. package/src/lib/components/console/pos/pos-api.js +13 -0
  34. package/src/lib/components/console/pos/pos-api.js.map +1 -1
  35. package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +12 -0
  36. package/src/lib/components/console/pos/pos-item-dialog.component.js +10 -8
  37. package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
  38. package/src/lib/components/console/pos/pos-kiosk-queue.component.d.ts +22 -0
  39. package/src/lib/components/console/pos/pos-kiosk-queue.component.js +168 -0
  40. package/src/lib/components/console/pos/pos-kiosk-queue.component.js.map +1 -0
  41. package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +18 -0
  42. package/src/lib/components/console/pos/pos-tender-dialogs.component.js +116 -1
  43. package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -1
  44. package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +8 -0
  45. package/src/lib/components/console/pos/pos-tender-panel.component.js +77 -18
  46. package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
  47. package/src/lib/components/console/pos/use-pos-display.d.ts +5 -2
  48. package/src/lib/components/console/pos/use-pos-display.js +3 -2
  49. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  50. package/src/lib/components/console/pos-devices-card.component.js +2 -2
  51. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  52. package/src/lib/components/console/pos-display/pairing-screen.d.ts +5 -2
  53. package/src/lib/components/console/pos-display/pairing-screen.js +7 -5
  54. package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -1
  55. package/src/lib/components/console/pos-display/pos-display-api.d.ts +7 -1
  56. package/src/lib/components/console/pos-display/pos-display-api.js +7 -2
  57. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  58. package/src/lib/components/console/pos-kiosk/kiosk-checkout.d.ts +41 -0
  59. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js +275 -0
  60. package/src/lib/components/console/pos-kiosk/kiosk-checkout.js.map +1 -0
  61. package/src/lib/components/console/pos-kiosk/kiosk-menu.d.ts +32 -0
  62. package/src/lib/components/console/pos-kiosk/kiosk-menu.js +344 -0
  63. package/src/lib/components/console/pos-kiosk/kiosk-menu.js.map +1 -0
  64. package/src/lib/components/console/pos-kiosk/kiosk-staff.d.ts +12 -0
  65. package/src/lib/components/console/pos-kiosk/kiosk-staff.js +257 -0
  66. package/src/lib/components/console/pos-kiosk/kiosk-staff.js.map +1 -0
  67. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.d.ts +114 -0
  68. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js +189 -0
  69. package/src/lib/components/console/pos-kiosk/pos-kiosk-api.js.map +1 -0
  70. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.d.ts +16 -0
  71. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js +80 -0
  72. package/src/lib/components/console/pos-kiosk/use-kiosk-idle.js.map +1 -0
  73. package/src/lib/components/console/pos-kiosk-page.component.d.ts +28 -0
  74. package/src/lib/components/console/pos-kiosk-page.component.js +791 -0
  75. package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -0
  76. package/src/lib/components/console/pos-offline/pos-offline-api.d.ts +44 -0
  77. package/src/lib/components/console/pos-offline/pos-offline-api.js +69 -0
  78. package/src/lib/components/console/pos-offline/pos-offline-api.js.map +1 -0
  79. package/src/lib/components/console/pos-offline/pos-offline-banner.component.d.ts +7 -0
  80. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js +135 -0
  81. package/src/lib/components/console/pos-offline/pos-offline-banner.component.js.map +1 -0
  82. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.d.ts +32 -0
  83. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js +287 -0
  84. package/src/lib/components/console/pos-offline/pos-offline-checkout.component.js.map +1 -0
  85. package/src/lib/components/console/pos-offline/pos-offline-store.d.ts +63 -0
  86. package/src/lib/components/console/pos-offline/pos-offline-store.js +145 -0
  87. package/src/lib/components/console/pos-offline/pos-offline-store.js.map +1 -0
  88. package/src/lib/components/console/pos-offline/register-offline.d.ts +24 -0
  89. package/src/lib/components/console/pos-offline/register-offline.js +24 -0
  90. package/src/lib/components/console/pos-offline/register-offline.js.map +1 -0
  91. package/src/lib/components/console/pos-offline/use-pos-offline.d.ts +85 -0
  92. package/src/lib/components/console/pos-offline/use-pos-offline.js +542 -0
  93. package/src/lib/components/console/pos-offline/use-pos-offline.js.map +1 -0
  94. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +72 -17
  95. package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -1
  96. package/src/lib/components/console/pos-page.component.js +228 -51
  97. package/src/lib/components/console/pos-page.component.js.map +1 -1
  98. package/src/lib/components/console/pos-zones.d.ts +23 -0
  99. package/src/lib/components/console/pos-zones.js +31 -0
  100. package/src/lib/components/console/pos-zones.js.map +1 -0
  101. package/src/lib/components/console/product-editor-dialog.component.js +10 -64
  102. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  103. package/src/lib/components/console/products-hub-card.component.js +46 -30
  104. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  105. package/src/lib/components/console/shipping-settings-card.component.js +1 -1
  106. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
  107. package/src/lib/components/console/stock-movements-card.component.js +48 -16
  108. package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
  109. package/src/lib/components/console/store-zones.d.ts +8 -1
  110. package/src/lib/components/console/store-zones.js +11 -1
  111. package/src/lib/components/console/store-zones.js.map +1 -1
  112. package/src/lib/components/console/storefront-tax-summary-card.component.js +1 -0
  113. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -1
  114. package/src/lib/components/order-status.js +66 -0
  115. package/src/lib/components/order-status.js.map +1 -1
  116. package/src/lib/components/product-detail.js +42 -15
  117. package/src/lib/components/product-detail.js.map +1 -1
  118. package/src/lib/constants/local-fulfillment-list-query.d.ts +48 -0
  119. package/src/lib/constants/local-fulfillment-list-query.js +84 -0
  120. package/src/lib/constants/local-fulfillment-list-query.js.map +1 -0
  121. package/src/lib/constants/orders-list-query.d.ts +7 -2
  122. package/src/lib/constants/orders-list-query.js +89 -8
  123. package/src/lib/constants/orders-list-query.js.map +1 -1
  124. package/src/lib/constants/pos-shift-list-query.d.ts +22 -0
  125. package/src/lib/constants/pos-shift-list-query.js +115 -0
  126. package/src/lib/constants/pos-shift-list-query.js.map +1 -0
  127. package/src/lib/constants/product-list-query.d.ts +6 -1
  128. package/src/lib/constants/product-list-query.js +77 -8
  129. package/src/lib/constants/product-list-query.js.map +1 -1
  130. package/src/lib/constants/stock-movement-query.d.ts +3 -2
  131. package/src/lib/constants/stock-movement-query.js +52 -8
  132. package/src/lib/constants/stock-movement-query.js.map +1 -1
  133. package/src/lib/declarations.server.js +21 -0
  134. package/src/lib/declarations.server.js.map +1 -1
  135. package/src/lib/model/buyer-notifications.d.ts +5 -3
  136. package/src/lib/model/buyer-notifications.js +25 -4
  137. package/src/lib/model/buyer-notifications.js.map +1 -1
  138. package/src/lib/model/commerce-orders.d.ts +103 -1
  139. package/src/lib/model/commerce-orders.js +2 -1
  140. package/src/lib/model/commerce-orders.js.map +1 -1
  141. package/src/lib/model/commerce-pos-kiosk.d.ts +175 -0
  142. package/src/lib/model/commerce-pos-kiosk.js +147 -0
  143. package/src/lib/model/commerce-pos-kiosk.js.map +1 -0
  144. package/src/lib/model/commerce-pos-offline.d.ts +234 -0
  145. package/src/lib/model/commerce-pos-offline.js +301 -0
  146. package/src/lib/model/commerce-pos-offline.js.map +1 -0
  147. package/src/lib/model/commerce-pos-ops.d.ts +16 -6
  148. package/src/lib/model/commerce-pos-ops.js +12 -4
  149. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  150. package/src/lib/model/commerce-pos.d.ts +13 -1
  151. package/src/lib/model/commerce-pos.js +5 -4
  152. package/src/lib/model/commerce-pos.js.map +1 -1
  153. package/src/lib/model/commerce-stock-holds.d.ts +24 -3
  154. package/src/lib/model/commerce-stock-holds.js +26 -8
  155. package/src/lib/model/commerce-stock-holds.js.map +1 -1
  156. package/src/lib/model/commerce.d.ts +7 -1
  157. package/src/lib/model/commerce.js.map +1 -1
  158. package/src/lib/model/index.d.ts +5 -0
  159. package/src/lib/model/index.js +5 -0
  160. package/src/lib/model/index.js.map +1 -1
  161. package/src/lib/model/local-fulfillment-settings.d.ts +178 -0
  162. package/src/lib/model/local-fulfillment-settings.js +361 -0
  163. package/src/lib/model/local-fulfillment-settings.js.map +1 -0
  164. package/src/lib/model/order-list-fields.d.ts +10 -1
  165. package/src/lib/model/order-list-fields.js +1 -0
  166. package/src/lib/model/order-list-fields.js.map +1 -1
  167. package/src/lib/model/order-local-fulfillment.d.ts +131 -0
  168. package/src/lib/model/order-local-fulfillment.js +125 -0
  169. package/src/lib/model/order-local-fulfillment.js.map +1 -0
  170. package/src/lib/model/order-shipping-export.js +4 -0
  171. package/src/lib/model/order-shipping-export.js.map +1 -1
  172. package/src/lib/model/order-status-view.d.ts +20 -1
  173. package/src/lib/model/order-status-view.js +60 -6
  174. package/src/lib/model/order-status-view.js.map +1 -1
  175. package/src/lib/model/product-write.d.ts +186 -0
  176. package/src/lib/model/product-write.js +116 -0
  177. package/src/lib/model/product-write.js.map +1 -0
  178. package/src/lib/plugin-config.js +6 -2
  179. package/src/lib/plugin-config.js.map +1 -1
  180. package/src/lib/plugin.js +11 -0
  181. package/src/lib/plugin.js.map +1 -1
  182. package/src/lib/pos-kiosk-config.d.ts +26 -0
  183. package/src/lib/pos-kiosk-config.js +59 -0
  184. package/src/lib/pos-kiosk-config.js.map +1 -0
  185. package/src/lib/server/api-v1/openapi.js +8 -0
  186. package/src/lib/server/api-v1/openapi.js.map +1 -1
  187. package/src/lib/server/api-v1/order-view.d.ts +19 -0
  188. package/src/lib/server/api-v1/order-view.js +35 -0
  189. package/src/lib/server/api-v1/order-view.js.map +1 -1
  190. package/src/lib/server/billing-webhook.js +238 -87
  191. package/src/lib/server/billing-webhook.js.map +1 -1
  192. package/src/lib/server/cart-checkout.d.ts +2 -0
  193. package/src/lib/server/cart-checkout.js +173 -13
  194. package/src/lib/server/cart-checkout.js.map +1 -1
  195. package/src/lib/server/channel-order-updates.d.ts +50 -0
  196. package/src/lib/server/channel-order-updates.js +290 -0
  197. package/src/lib/server/channel-order-updates.js.map +1 -0
  198. package/src/lib/server/channel-orders.d.ts +85 -0
  199. package/src/lib/server/channel-orders.js +543 -0
  200. package/src/lib/server/channel-orders.js.map +1 -0
  201. package/src/lib/server/checkout-extras.js +18 -4
  202. package/src/lib/server/checkout-extras.js.map +1 -1
  203. package/src/lib/server/checkout.js +71 -14
  204. package/src/lib/server/checkout.js.map +1 -1
  205. package/src/lib/server/local-fulfillment-status.d.ts +86 -0
  206. package/src/lib/server/local-fulfillment-status.js +379 -0
  207. package/src/lib/server/local-fulfillment-status.js.map +1 -0
  208. package/src/lib/server/local-fulfillment.d.ts +190 -0
  209. package/src/lib/server/local-fulfillment.js +580 -0
  210. package/src/lib/server/local-fulfillment.js.map +1 -0
  211. package/src/lib/server/membership-register.js +3 -1
  212. package/src/lib/server/membership-register.js.map +1 -1
  213. package/src/lib/server/order-notifications.js +61 -0
  214. package/src/lib/server/order-notifications.js.map +1 -1
  215. package/src/lib/server/pos-display.d.ts +27 -1
  216. package/src/lib/server/pos-display.js +50 -9
  217. package/src/lib/server/pos-display.js.map +1 -1
  218. package/src/lib/server/pos-kiosk-principal.d.ts +29 -0
  219. package/src/lib/server/pos-kiosk-principal.js +42 -0
  220. package/src/lib/server/pos-kiosk-principal.js.map +1 -0
  221. package/src/lib/server/pos-kiosk.d.ts +54 -0
  222. package/src/lib/server/pos-kiosk.js +972 -0
  223. package/src/lib/server/pos-kiosk.js.map +1 -0
  224. package/src/lib/server/pos-offline-sync.d.ts +85 -0
  225. package/src/lib/server/pos-offline-sync.js +765 -0
  226. package/src/lib/server/pos-offline-sync.js.map +1 -0
  227. package/src/lib/server/pos-order.js +22 -4
  228. package/src/lib/server/pos-order.js.map +1 -1
  229. package/src/lib/server/pos-payment.d.ts +6 -0
  230. package/src/lib/server/pos-payment.js +225 -6
  231. package/src/lib/server/pos-payment.js.map +1 -1
  232. package/src/lib/server/pos-print.js +5 -0
  233. package/src/lib/server/pos-print.js.map +1 -1
  234. package/src/lib/server/pos-return.js +27 -0
  235. package/src/lib/server/pos-return.js.map +1 -1
  236. package/src/lib/server/pos-sale.d.ts +6 -0
  237. package/src/lib/server/pos-sale.js +2 -0
  238. package/src/lib/server/pos-sale.js.map +1 -1
  239. package/src/lib/server/pos-shift.js +8 -1
  240. package/src/lib/server/pos-shift.js.map +1 -1
  241. package/src/lib/server/product-catalog.js +5 -1
  242. package/src/lib/server/product-catalog.js.map +1 -1
  243. package/src/lib/server/product-drafts.d.ts +5 -1
  244. package/src/lib/server/product-drafts.js +3 -3
  245. package/src/lib/server/product-drafts.js.map +1 -1
  246. package/src/lib/server/product-writer.d.ts +19 -0
  247. package/src/lib/server/product-writer.js +261 -0
  248. package/src/lib/server/product-writer.js.map +1 -0
  249. package/src/lib/server/products-write.d.ts +61 -0
  250. package/src/lib/server/products-write.js +375 -0
  251. package/src/lib/server/products-write.js.map +1 -0
  252. package/src/lib/server/refund.js +3 -0
  253. package/src/lib/server/refund.js.map +1 -1
  254. package/src/lib/server/stock-hold.d.ts +9 -1
  255. package/src/lib/server/stock-hold.js +15 -7
  256. package/src/lib/server/stock-hold.js.map +1 -1
  257. package/src/lib/server.js +21 -0
  258. package/src/lib/server.js.map +1 -1
  259. package/src/lib/tenant-emails.js +161 -0
  260. package/src/lib/tenant-emails.js.map +1 -1
  261. package/src/lib/testing/memory-firestore.d.ts +16 -3
  262. package/src/lib/testing/memory-firestore.js +11 -3
  263. package/src/lib/testing/memory-firestore.js.map +1 -1
  264. package/src/lib/transfer/products.server.d.ts +5 -0
  265. package/src/lib/transfer/products.server.js +2 -2
  266. package/src/lib/transfer/products.server.js.map +1 -1
@@ -22,15 +22,16 @@ import { PRODUCT_LIST_BASE, PRODUCT_LIST_QUERY } from "../../constants/product-l
22
22
  import { NextPageTitle } from "@aglyn/shared-ui-next/contexts/next-page-title-provider";
23
23
  import { useSnackbar } from "@aglyn/shared-ui-snackstack";
24
24
  import { planListQuery } from "@aglyn/shared-ui-jsx/const/list-query-plan";
25
+ import { useViewportFill } from "@aglyn/shared-ui-jsx/hooks/use-viewport-fill";
25
26
  import { nameSearchNormalizers } from "@aglyn/aglyn/app-utils/name-search";
26
- import { Badge, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Drawer, MenuItem, Stack, TextField, Typography, useMediaQuery, useTheme } from "@mui/material";
27
+ import { Badge, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Drawer, MenuItem, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography, useMediaQuery, useTheme } from "@mui/material";
27
28
  import { collection, getDocs, limit, query, where } from "firebase/firestore";
28
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
29
+ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
29
30
  import { useFirestore, useUser } from "@aglyn/tenant-feature-instance";
30
31
  import { useFirestoreCollection } from "@aglyn/tenant-feature-instance";
31
32
  import { listQueryConstraints } from "@aglyn/tenant-feature-instance/hooks/use-list-query";
32
33
  import { useOrgPlan } from "@aglyn/tenant-feature-instance";
33
- import { newAttemptKey, openPosSale, posRegisterContext, PosRequestError, usd } from "./pos/pos-api.js";
34
+ import { newAttemptKey, openPosSale, posRegisterContext, posTender, PosRequestError, usd } from "./pos/pos-api.js";
34
35
  import { PosCartPanel } from "./pos/pos-cart-panel.component.js";
35
36
  import { ScanAdornment } from "../../barcode/scan-button.component.js";
36
37
  import { useScannerWedge } from "../../barcode/scanner-wedge.js";
@@ -39,7 +40,11 @@ import { POS_QUICK_KEYS, POS_TOUCH_PX, PosProductGrid } from "./pos/pos-product-
39
40
  import { PosItemDialog, posItemNeedsChoice } from "./pos/pos-item-dialog.component.js";
40
41
  import { PosReceiptPanel } from "./pos/pos-receipt-panel.component.js";
41
42
  import { PosTenderPanel } from "./pos/pos-tender-panel.component.js";
43
+ import { PosKioskQueue } from "./pos/pos-kiosk-queue.component.js";
42
44
  import { posDisplayTipCents, usePosDisplay } from "./pos/use-pos-display.js";
45
+ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot-context";
46
+ import { POS_ORDERS_ZONE } from "./pos-zones.js";
47
+ import { PosOfflineBanner, PosOfflineCheckout, usePosOffline } from "./pos-offline/register-offline.js";
43
48
  /** The till sells active products only; every read of the catalog asks it. */ const SELLABLE = {
44
49
  field: 'status',
45
50
  op: 'equals',
@@ -167,9 +172,23 @@ import { posDisplayTipCents, usePosDisplay } from "./pos/use-pos-display.js";
167
172
  var _line_variantId;
168
173
  return `${line.productId}:${(_line_variantId = line.variantId) != null ? _line_variantId : ''}:${CommerceModel.modifierSelectionKey(line.modifiers)}`;
169
174
  }
175
+ /**
176
+ * The register's zone (AGL-3644), drawn again only when what it is handed
177
+ * changes: the till redraws on every tap, and the shell's renderer is not
178
+ * memoized (the order dialog's reasoning).
179
+ */ const PosOrdersZone = /*#__PURE__*/ memo(function PosOrdersZone(props) {
180
+ const { renderer: Renderer, hostId, registerId } = props;
181
+ return /*#__PURE__*/ _jsx(Renderer, {
182
+ slot: POS_ORDERS_ZONE.id,
183
+ hostId: hostId,
184
+ orgId: undefined,
185
+ registerId: registerId
186
+ });
187
+ });
170
188
  export function PosConsolePage({ hostId }) {
171
- var _ref, _ref1, _ref2, _ref3, _ref4;
172
- var _usableRegisters_find, _usableRegisters_;
189
+ var _ref, _ref1, _ref2, _liveRegister_openShiftId, _ref3, _ref4, _ref5, _ref6;
190
+ var _usableRegisters_find, _usableRegisters_, _offline_totalsFor;
191
+ const WidgetSlot = useConsoleWidgetSlot();
173
192
  const firestore = useFirestore();
174
193
  const { data: user } = useUser();
175
194
  const { enqueueSnackbar } = useSnackbar();
@@ -315,6 +334,9 @@ export function PosConsolePage({ hostId }) {
315
334
  * whenever the basket changes, so a retried Charge finds the same sale and
316
335
  * ringing the same coffee twice is two sales.
317
336
  */ const attemptKey = useRef('');
337
+ const fill = useViewportFill({
338
+ min: 480
339
+ });
318
340
  useEffect(()=>{
319
341
  attemptKey.current = '';
320
342
  }, [
@@ -328,11 +350,53 @@ export function PosConsolePage({ hostId }) {
328
350
  })), [
329
351
  productDocs
330
352
  ]);
331
- const productsById = useMemo(()=>new Map(products.map((product)=>[
353
+ /*
354
+ * THE OFFLINE REGISTER (AGL-3625): the catalog and the site's offline rules
355
+ * kept on this device, the queue of cash sales rung without a connection,
356
+ * and the sync that records them once it returns.
357
+ */ const loadCatalog = useCallback(async ()=>(await getDocs(query(collection(firestore, 'hosts', hostId, 'products'), ...listQueryConstraints(posProductPlan({})), limit(POS_GRID_CEILING)))).docs.map((snapshot)=>_extends({}, snapshot.data(), {
358
+ $id: snapshot.id
359
+ })), [
360
+ firestore,
361
+ hostId
362
+ ]);
363
+ const liveRegister = usableRegisters.find((register)=>register.$id === registerId);
364
+ const offline = usePosOffline(_extends({
365
+ hostId,
366
+ user,
367
+ registerId,
368
+ openShiftId: liveRegister ? (_liveRegister_openShiftId = liveRegister.openShiftId) != null ? _liveRegister_openShiftId : null : undefined,
369
+ locationId
370
+ }, cashier.assertion ? {
371
+ cashierAssertion: cashier.assertion
372
+ } : {}, {
373
+ liveProducts: products,
374
+ loadCatalog
375
+ }));
376
+ const [offlineCheckout, setOfflineCheckout] = useState(false);
377
+ /** Open sales left unpaid when the connection dropped, voided once it returns. */ const strandedSales = useRef([]);
378
+ useEffect(()=>{
379
+ if (offline.offline || !user || !strandedSales.current.length) return;
380
+ const orderIds = strandedSales.current.splice(0);
381
+ for (const orderId of orderIds){
382
+ void posTender(user, hostId, orderId, 'void').catch(()=>undefined);
383
+ }
384
+ }, [
385
+ offline.offline,
386
+ user,
387
+ hostId
388
+ ]);
389
+ const sellProducts = useMemo(()=>offline.offline && offline.ready ? offline.gridProducts(search, categoryId, POS_QUICK_KEYS) : products, [
390
+ offline,
391
+ search,
392
+ categoryId,
393
+ products
394
+ ]);
395
+ const productsById = useMemo(()=>new Map(sellProducts.map((product)=>[
332
396
  product.$id,
333
397
  product
334
398
  ])), [
335
- products
399
+ sellProducts
336
400
  ]);
337
401
  /** AGL-2357: warns, never blocks. */ const shortfalls = useMemo(()=>lines.map((line)=>{
338
402
  var _line_variantId;
@@ -357,6 +421,18 @@ export function PosConsolePage({ hostId }) {
357
421
  }, [
358
422
  enqueueSnackbar
359
423
  ]);
424
+ /** A pairing code for a customer display or a self-service kiosk (AGL-3623). */ const showPairingCode = useCallback(async (mode)=>{
425
+ try {
426
+ setPairing(_extends({}, await display.pairingCode(mode), {
427
+ mode
428
+ }));
429
+ } catch (error) {
430
+ notify(error instanceof PosRequestError ? error.message : 'Could not make a code', 'error');
431
+ }
432
+ }, [
433
+ display,
434
+ notify
435
+ ]);
360
436
  /**
361
437
  * Adds a line, or more of an identical one: the same product, variant and
362
438
  * modifiers merge, so two oat lattes are one line of two and an oat latte
@@ -416,6 +492,13 @@ export function PosConsolePage({ hostId }) {
416
492
  var _product_variants_find;
417
493
  const needle = scanned.trim().toLowerCase();
418
494
  if (!needle || sale) return;
495
+ if (offline.offline) {
496
+ const found = offline.findByCode(needle);
497
+ if (!found) return void notify(`No product matches “${scanned.trim()}”`, 'warning');
498
+ tapProduct(found.product, found.variant);
499
+ setSearch('');
500
+ return;
501
+ }
419
502
  const lookup = async (field)=>{
420
503
  const found = await getDocs(query(collection(firestore, 'hosts', hostId, 'products'), ...listQueryConstraints(posProductPlan({
421
504
  code: {
@@ -431,6 +514,7 @@ export function PosConsolePage({ hostId }) {
431
514
  hit = (_ref = await lookup('barcodes')) != null ? _ref : await lookup('skus');
432
515
  } catch (error) {
433
516
  console.error(error);
517
+ offline.reportNetworkFailure();
434
518
  return void notify('Could not reach the catalog — try again', 'warning');
435
519
  }
436
520
  if (!hit) return void notify(`No product matches “${scanned.trim()}”`, 'warning');
@@ -450,7 +534,8 @@ export function PosConsolePage({ hostId }) {
450
534
  firestore,
451
535
  hostId,
452
536
  tapProduct,
453
- notify
537
+ notify,
538
+ offline
454
539
  ]);
455
540
  const handleSearchEnter = useCallback(()=>lookupCode(search), [
456
541
  lookupCode,
@@ -472,6 +557,13 @@ export function PosConsolePage({ hostId }) {
472
557
  const charge = useCallback(async ()=>{
473
558
  if (chargeInFlight.current || lines.length === 0 || !user) return;
474
559
  if (!registerId) return void notify('Select a register before taking payment', 'warning');
560
+ // Offline, the basket rings as a cash sale kept on this register (AGL-3625).
561
+ if (offline.offline) {
562
+ var _offline_unavailableReason;
563
+ if (!offline.ready) return void notify((_offline_unavailableReason = offline.unavailableReason) != null ? _offline_unavailableReason : 'Offline selling is unavailable', 'warning');
564
+ setOfflineCheckout(true);
565
+ return;
566
+ }
475
567
  if (!attemptKey.current) attemptKey.current = newAttemptKey();
476
568
  chargeInFlight.current = true;
477
569
  setOpening(true);
@@ -503,7 +595,13 @@ export function PosConsolePage({ hostId }) {
503
595
  });
504
596
  setSheetOpen(true);
505
597
  } catch (error) {
506
- notify(error instanceof PosRequestError ? error.message : 'Sale failed', 'error');
598
+ if (error instanceof PosRequestError) {
599
+ notify(error.message, 'error');
600
+ } else {
601
+ // The request never reached the server: the register is offline.
602
+ offline.reportNetworkFailure();
603
+ notify('The register lost its connection. Charge again to take cash offline.', 'warning');
604
+ }
507
605
  } finally{
508
606
  chargeInFlight.current = false;
509
607
  setOpening(false);
@@ -518,7 +616,8 @@ export function PosConsolePage({ hostId }) {
518
616
  customer,
519
617
  cashier.assertion,
520
618
  locationId,
521
- notify
619
+ notify,
620
+ offline
522
621
  ]);
523
622
  const resetSale = useCallback(()=>{
524
623
  if ((sale == null ? void 0 : sale.status) === 'paid') setLastReceipt({
@@ -668,13 +767,7 @@ export function PosConsolePage({ hostId }) {
668
767
  }),
669
768
  registerId ? /*#__PURE__*/ _jsx(Button, {
670
769
  size: "small",
671
- onClick: async ()=>{
672
- try {
673
- setPairing(await display.pairingCode());
674
- } catch (error) {
675
- notify(error instanceof PosRequestError ? error.message : 'Could not make a code', 'error');
676
- }
677
- },
770
+ onClick: ()=>void showPairingCode('display'),
678
771
  children: display.connected ? 'Display connected' : 'Pair display'
679
772
  }) : null
680
773
  ]
@@ -774,8 +867,18 @@ export function PosConsolePage({ hostId }) {
774
867
  }, cashier.assertion ? {
775
868
  cashierAssertion: cashier.assertion
776
869
  } : {}, {
777
- notify: notify
778
- })) : /*#__PURE__*/ _jsxs(_Fragment, {
870
+ notify: notify,
871
+ offline: offline.offline
872
+ }, offline.ready ? {
873
+ onSellOffline: ()=>{
874
+ // The server's open sale took no payment; it is voided once
875
+ // the connection returns, and the basket rings offline.
876
+ strandedSales.current.push(sale.orderId);
877
+ setSale(null);
878
+ setSaleLines([]);
879
+ setOfflineCheckout(true);
880
+ }
881
+ } : {})) : /*#__PURE__*/ _jsxs(_Fragment, {
779
882
  children: [
780
883
  /*#__PURE__*/ _jsxs(Box, {
781
884
  sx: {
@@ -806,7 +909,7 @@ export function PosConsolePage({ hostId }) {
806
909
  sx: {
807
910
  minHeight: 56
808
911
  },
809
- children: opening ? 'Pricing…' : `Charge ${usd(estimateCents)}`
912
+ children: opening ? 'Pricing…' : offline.offline ? `Cash ${usd((_ref4 = (_offline_totalsFor = offline.totalsFor(lines, discountPct)) == null ? void 0 : _offline_totalsFor.totalCents) != null ? _ref4 : estimateCents)} (offline)` : `Charge ${usd(estimateCents)}`
810
913
  }),
811
914
  lastReceipt ? /*#__PURE__*/ _jsx(PosLastReceipt, _extends({
812
915
  hostId: hostId,
@@ -826,42 +929,75 @@ export function PosConsolePage({ hostId }) {
826
929
  screen: 'POS'
827
930
  }),
828
931
  /*#__PURE__*/ _jsxs(Box, {
932
+ ref: fill.ref,
829
933
  sx: {
830
934
  display: 'flex',
831
- height: '100dvh',
935
+ // From under the console's header, nav and page title to the
936
+ // bottom of the window, not a whole window tall below them.
937
+ height: fill.height,
832
938
  overflow: 'hidden'
833
939
  },
834
940
  children: [
835
- /*#__PURE__*/ _jsx(Box, {
941
+ /*#__PURE__*/ _jsxs(Box, {
836
942
  sx: {
837
943
  flex: 1,
838
944
  p: 2,
839
945
  overflowY: 'auto',
840
946
  pb: wide ? 2 : 12
841
947
  },
842
- children: /*#__PURE__*/ _jsx(PosProductGrid, {
843
- search: search,
844
- onSearch: setSearch,
845
- onSearchEnter: ()=>void handleSearchEnter(),
846
- scanAdornment: scanAdornment,
847
- categories: (categoryDocs != null ? categoryDocs : []).map((category)=>{
848
- var _category_name;
849
- return {
850
- $id: category.$id,
851
- name: String((_category_name = category.name) != null ? _category_name : 'Category')
852
- };
948
+ children: [
949
+ /*#__PURE__*/ _jsx(Box, {
950
+ sx: {
951
+ mb: 2,
952
+ '&:empty': {
953
+ display: 'none'
954
+ }
955
+ },
956
+ children: /*#__PURE__*/ _jsx(PosOfflineBanner, {
957
+ offline: offline
958
+ })
853
959
  }),
854
- categoryId: categoryId,
855
- onCategory: setCategoryId,
856
- notices: gridPlan.notices,
857
- hostId: hostId,
858
- products: products,
859
- basketCounts: basketCounts,
860
- onTap: (product)=>{
861
- if (sale) return void notify('Finish or void the open sale first', 'info');
862
- tapProduct(product);
863
- }
864
- })
960
+ registerId ? /*#__PURE__*/ _jsx(PosKioskQueue, {
961
+ user: user,
962
+ hostId: hostId,
963
+ registerId: registerId,
964
+ disabled: Boolean(sale),
965
+ onTake: (next, nextLines)=>{
966
+ setSaleLines(nextLines);
967
+ setSale(next);
968
+ setSheetOpen(true);
969
+ },
970
+ notify: notify
971
+ }) : null,
972
+ WidgetSlot ? /*#__PURE__*/ _jsx(PosOrdersZone, {
973
+ renderer: WidgetSlot,
974
+ hostId: hostId,
975
+ registerId: registerId || null
976
+ }) : null,
977
+ /*#__PURE__*/ _jsx(PosProductGrid, {
978
+ search: search,
979
+ onSearch: setSearch,
980
+ onSearchEnter: ()=>void handleSearchEnter(),
981
+ scanAdornment: scanAdornment,
982
+ categories: (categoryDocs != null ? categoryDocs : []).map((category)=>{
983
+ var _category_name;
984
+ return {
985
+ $id: category.$id,
986
+ name: String((_category_name = category.name) != null ? _category_name : 'Category')
987
+ };
988
+ }),
989
+ categoryId: categoryId,
990
+ onCategory: setCategoryId,
991
+ notices: gridPlan.notices,
992
+ hostId: hostId,
993
+ products: sellProducts,
994
+ basketCounts: basketCounts,
995
+ onTap: (product)=>{
996
+ if (sale) return void notify('Finish or void the open sale first', 'info');
997
+ tapProduct(product);
998
+ }
999
+ })
1000
+ ]
865
1001
  }),
866
1002
  wide ? /*#__PURE__*/ _jsx(Box, {
867
1003
  sx: {
@@ -949,7 +1085,7 @@ export function PosConsolePage({ hostId }) {
949
1085
  ]
950
1086
  }) : null,
951
1087
  /*#__PURE__*/ _jsx(PosItemDialog, _extends({
952
- product: (_ref4 = itemSheet == null ? void 0 : itemSheet.product) != null ? _ref4 : null,
1088
+ product: (_ref5 = itemSheet == null ? void 0 : itemSheet.product) != null ? _ref5 : null,
953
1089
  initial: itemSheet == null ? void 0 : itemSheet.initial,
954
1090
  onClose: ()=>setItemSheet(null),
955
1091
  onConfirm: (choice)=>{
@@ -970,6 +1106,28 @@ export function PosConsolePage({ hostId }) {
970
1106
  setLines((prev)=>prev.filter((_line, index)=>index !== at));
971
1107
  }
972
1108
  } : {})),
1109
+ /*#__PURE__*/ _jsx(PosOfflineCheckout, _extends({
1110
+ open: offlineCheckout,
1111
+ offline: offline,
1112
+ hostId: hostId,
1113
+ lines: lines,
1114
+ discountPct: discountPct,
1115
+ customer: customer
1116
+ }, registerName ? {
1117
+ registerName
1118
+ } : {}, cashier.cashier ? {
1119
+ cashierName: cashier.cashier.name
1120
+ } : {}, {
1121
+ onClose: ()=>setOfflineCheckout(false),
1122
+ onRung: ()=>undefined,
1123
+ onDone: ()=>{
1124
+ setOfflineCheckout(false);
1125
+ setLines([]);
1126
+ setDiscountPct(0);
1127
+ setCustomer(null);
1128
+ setSheetOpen(false);
1129
+ }
1130
+ })),
973
1131
  /*#__PURE__*/ _jsxs(Dialog, {
974
1132
  open: Boolean(pairing),
975
1133
  onClose: ()=>setPairing(null),
@@ -977,7 +1135,7 @@ export function PosConsolePage({ hostId }) {
977
1135
  fullWidth: true,
978
1136
  children: [
979
1137
  /*#__PURE__*/ _jsx(DialogTitle, {
980
- children: 'Pair a customer display'
1138
+ children: (pairing == null ? void 0 : pairing.mode) === 'kiosk' ? 'Pair a self-service kiosk' : 'Pair a customer display'
981
1139
  }),
982
1140
  /*#__PURE__*/ _jsxs(DialogContent, {
983
1141
  sx: {
@@ -986,20 +1144,39 @@ export function PosConsolePage({ hostId }) {
986
1144
  gap: 2
987
1145
  },
988
1146
  children: [
989
- /*#__PURE__*/ _jsx(Typography, {
990
- variant: "body2",
991
- color: "text.secondary",
1147
+ /*#__PURE__*/ _jsxs(ToggleButtonGroup, {
1148
+ exclusive: true,
1149
+ fullWidth: true,
1150
+ size: "small",
1151
+ value: (_ref6 = pairing == null ? void 0 : pairing.mode) != null ? _ref6 : 'display',
1152
+ onChange: (_event, mode)=>{
1153
+ if (mode && mode !== (pairing == null ? void 0 : pairing.mode)) void showPairingCode(mode);
1154
+ },
992
1155
  sx: {
993
1156
  mt: 1
994
1157
  },
995
- children: 'On the tablet facing your customer, open this address and enter the code. ' + 'The code works once and expires in 10 minutes.'
1158
+ children: [
1159
+ /*#__PURE__*/ _jsx(ToggleButton, {
1160
+ value: "display",
1161
+ children: 'Customer display'
1162
+ }),
1163
+ /*#__PURE__*/ _jsx(ToggleButton, {
1164
+ value: "kiosk",
1165
+ children: 'Self-service kiosk'
1166
+ })
1167
+ ]
1168
+ }),
1169
+ /*#__PURE__*/ _jsx(Typography, {
1170
+ variant: "body2",
1171
+ color: "text.secondary",
1172
+ children: ((pairing == null ? void 0 : pairing.mode) === 'kiosk' ? 'On the tablet customers order from, open this address and enter the code. ' : 'On the tablet facing your customer, open this address and enter the code. ') + 'The code works once and expires in 10 minutes.'
996
1173
  }),
997
1174
  /*#__PURE__*/ _jsx(Typography, {
998
1175
  variant: "body1",
999
1176
  sx: {
1000
1177
  wordBreak: 'break-all'
1001
1178
  },
1002
- children: `${typeof window === 'undefined' ? '' : window.location.origin}/kiosk/commerce/pos-display`
1179
+ children: `${typeof window === 'undefined' ? '' : window.location.origin}/kiosk/commerce/${(pairing == null ? void 0 : pairing.mode) === 'kiosk' ? 'pos-kiosk' : 'pos-display'}`
1003
1180
  }),
1004
1181
  /*#__PURE__*/ _jsx(Typography, {
1005
1182
  variant: "h3",